home *** CD-ROM | disk | FTP | other *** search
/ Risc World 3 / Risc World 3.iso / SOFTWARE / ISSUE6 / PD / PDF / xpdf / c++ / FontFile next >
Text File  |  2003-02-21  |  117KB  |  3,947 lines

  1. //========================================================================
  2. //
  3. // FontFile.cc
  4. //
  5. // Copyright 1999-2002 Glyph & Cog, LLC
  6. //
  7. //========================================================================
  8.  
  9. //========================================================================
  10. //
  11. // Changes marked:
  12. //
  13. //   //**** Colin Granville ****
  14. // To
  15. //   //**** end Colin Granville ****
  16. //
  17. // made by Colin Granville 2003
  18. //
  19. //========================================================================
  20.  
  21. #include <aconf.h>
  22.  
  23. #ifdef USE_GCC_PRAGMAS
  24. #pragma implementation
  25. #endif
  26.  
  27. #include <math.h>
  28. #include <stdlib.h>
  29. #include <stddef.h>
  30. #include <stdarg.h>
  31. #include <string.h>
  32. #include <ctype.h>
  33. #include "gmem.h"
  34. #include "Error.h"
  35. #include "GlobalParams.h"
  36. #include "CharCodeToUnicode.h"
  37. #include "FontEncodingTables.h"
  38. #include "FontFile.h"
  39.  
  40. #include "CompactFontTables.h"
  41.  
  42. //------------------------------------------------------------------------
  43.  
  44. static inline char *nextLine(char *line, char *end) {
  45.   while (line < end && *line != '\n' && *line != '\r')
  46.     ++line;
  47.   while (line < end && *line == '\n' || *line == '\r')
  48.     ++line;
  49.   return line;
  50. }
  51.  
  52. static char hexChars[17] = "0123456789ABCDEF";
  53.  
  54. //------------------------------------------------------------------------
  55. // FontFile
  56. //------------------------------------------------------------------------
  57.  
  58. FontFile::FontFile() {
  59. }
  60.  
  61. FontFile::~FontFile() {
  62. }
  63.  
  64. //------------------------------------------------------------------------
  65. // Type1FontFile
  66. //------------------------------------------------------------------------
  67.  
  68. Type1FontFile::Type1FontFile(char *file, int len) {
  69.   char *line, *line1, *p, *p2;
  70.   GBool haveEncoding;
  71.   char buf[256];
  72.   char c;
  73.   int n, code, i, j;
  74.  
  75.   name = NULL;
  76.   encoding = (char **)gmalloc(256 * sizeof(char *));
  77.   for (i = 0; i < 256; ++i) {
  78.     encoding[i] = NULL;
  79.   }
  80.   haveEncoding = gFalse;
  81.  
  82.   for (i = 1, line = file;
  83.        i <= 100 && line < file + len && !haveEncoding;
  84.        ++i) {
  85.  
  86.     // get font name
  87.     if (!strncmp(line, "/FontName", 9)) {
  88.       strncpy(buf, line, 255);
  89.       buf[255] = '\0';
  90.       if ((p = strchr(buf+9, '/')) &&
  91.           (p = strtok(p+1, " \t\n\r"))) {
  92.         name = copyString(p);
  93.       }
  94.       line = nextLine(line, file + len);
  95.  
  96.     // get encoding
  97.     } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
  98.       for (j = 0; j < 256; ++j) {
  99.         if (standardEncoding[j]) {
  100.           encoding[j] = copyString(standardEncoding[j]);
  101.         }
  102.       }
  103.       haveEncoding = gTrue;
  104.     } else if (!strncmp(line, "/Encoding 256 array", 19)) {
  105.       for (j = 0; j < 300; ++j) {
  106.         line1 = nextLine(line, file + len);
  107.         if ((n = line1 - line) > 255) {
  108.           n = 255;
  109.         }
  110.         strncpy(buf, line, n);
  111.         buf[n] = '\0';
  112.         for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
  113.         if (!strncmp(p, "dup", 3)) {
  114.           for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
  115.           for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
  116.           if (*p2) {
  117.             c = *p2;
  118.             *p2 = '\0';
  119.             if ((code = atoi(p)) < 256) {
  120.               *p2 = c;
  121.               for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
  122.               if (*p == '/') {
  123.                 ++p;
  124.                 for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
  125.                 *p2 = '\0';
  126.                 encoding[code] = copyString(p);
  127.               }
  128.             }
  129.           }
  130.         } else {
  131.           if (strtok(buf, " \t") &&
  132.               (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
  133.             break;
  134.           }
  135.         }
  136.         line = line1;
  137.       }
  138.       //~ check for getinterval/putinterval junk
  139.       haveEncoding = gTrue;
  140.  
  141.     } else {
  142.       line = nextLine(line, file + len);
  143.     }
  144.   }
  145. }
  146.  
  147. Type1FontFile::~Type1FontFile() {
  148.   int i;
  149.  
  150.   if (name) {
  151.     gfree(name);
  152.   }
  153.   for (i = 0; i < 256; ++i) {
  154.     gfree(encoding[i]);
  155.   }
  156.   gfree(encoding);
  157. }
  158.  
  159. //------------------------------------------------------------------------
  160. // Type1CFontFile
  161. //------------------------------------------------------------------------
  162.  
  163. struct Type1CTopDict {
  164.   int version;
  165.   int notice;
  166.   int copyright;
  167.   int fullName;
  168.   int familyName;
  169.   int weight;
  170.   int isFixedPitch;
  171.   double italicAngle;
  172.   double underlinePosition;
  173.   double underlineThickness;
  174.   int paintType;
  175.   int charstringType;
  176.   double fontMatrix[6];
  177.   int uniqueID;
  178.   double fontBBox[4];
  179.   double strokeWidth;
  180.   int charset;
  181.   int encoding;
  182.   int charStrings;
  183.   int privateSize;
  184.   int privateOffset;
  185.  
  186.   //----- CIDFont entries
  187.   int registry;
  188.   int ordering;
  189.   int supplement;
  190.   int fdArrayOffset;
  191.   int fdSelectOffset;
  192. };
  193.  
  194. struct Type1CPrivateDict {
  195.   GString *dictData;
  196.   int subrsOffset;
  197.   double defaultWidthX;
  198.   GBool defaultWidthXFP;
  199.   double nominalWidthX;
  200.   GBool nominalWidthXFP;
  201. };
  202.  
  203. Type1CFontFile::Type1CFontFile(char *fileA, int lenA) {
  204.   Guchar *nameIdxPtr, *idxPtr0, *idxPtr1;
  205.  
  206.   file = fileA;
  207.   len = lenA;
  208.   name = NULL;
  209.   encoding = NULL;
  210.  
  211.   // some tools embed Type 1C fonts with an extra whitespace char at
  212.   // the beginning
  213.   if (file[0] != '\x01') {
  214.     ++file;
  215.   }
  216.  
  217.   // read header
  218.   topOffSize = file[3] & 0xff;
  219.  
  220.   // read name index (first font only)
  221.   nameIdxPtr = (Guchar *)file + (file[2] & 0xff);
  222.   idxPtr0 = getIndexValPtr(nameIdxPtr, 0);
  223.   idxPtr1 = getIndexValPtr(nameIdxPtr, 1);
  224.   name = new GString((char *)idxPtr0, idxPtr1 - idxPtr0);
  225.  
  226.   topDictIdxPtr = getIndexEnd(nameIdxPtr);
  227.   stringIdxPtr = getIndexEnd(topDictIdxPtr);
  228.   gsubrIdxPtr = getIndexEnd(stringIdxPtr);
  229. }
  230.  
  231. Type1CFontFile::~Type1CFontFile() {
  232.   int i;
  233.  
  234.   delete name;
  235.   if (encoding) {
  236.     for (i = 0; i < 256; ++i) {
  237.       gfree(encoding[i]);
  238.     }
  239.     gfree(encoding);
  240.   }
  241. }
  242.  
  243. char *Type1CFontFile::getName() {
  244.   return name->getCString();
  245. }
  246.  
  247. char **Type1CFontFile::getEncoding() {
  248.   if (!encoding) {
  249.     readNameAndEncoding();
  250.   }
  251.   return encoding;
  252. }
  253.  
  254. void Type1CFontFile::readNameAndEncoding() {
  255.   char buf[256];
  256.   Guchar *idxPtr0, *idxPtr1, *ptr;
  257.   int nGlyphs;
  258.   int nCodes, nRanges, nLeft, nSups;
  259.   Gushort *glyphNames;
  260.   int charset, enc, charstrings;
  261.   int encFormat;
  262.   int c, sid;
  263.   double x;
  264.   GBool isFP;
  265.   int key;
  266.   int i, j;
  267.  
  268.   encoding = (char **)gmalloc(256 * sizeof(char *));
  269.   for (i = 0; i < 256; ++i) {
  270.     encoding[i] = NULL;
  271.   }
  272.  
  273.   // read top dict (first font only)
  274.   idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
  275.   idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
  276.   charset = enc = charstrings = 0;
  277.   i = 0;
  278.   ptr = idxPtr0;
  279.   while (ptr < idxPtr1) {
  280.     if (*ptr <= 27 || *ptr == 31) {
  281.       key = *ptr++;
  282.       if (key == 0x0c) {
  283.         key = (key << 8) | *ptr++;
  284.       }
  285.       if (key == 0x0f) { // charset
  286.         charset = (int)op[0];
  287.       } else if (key == 0x10) { // encoding
  288.         enc = (int)op[0];
  289.       } else if (key == 0x11) { // charstrings
  290.         charstrings = (int)op[0];
  291.       }
  292.       i = 0;
  293.     } else {
  294.       x = getNum(&ptr, &isFP);
  295.       if (i < 48) {
  296.         op[i++] = x;
  297.       }
  298.     }
  299.   }
  300.  
  301.   // get number of glyphs from charstrings index
  302.   nGlyphs = getIndexLen((Guchar *)file + charstrings);
  303.  
  304.   // read charset (GID -> name mapping)
  305.   glyphNames = readCharset(charset, nGlyphs);
  306.  
  307.   // read encoding (GID -> code mapping)
  308.   if (enc == 0) {
  309.     for (i = 0; i < 256; ++i) {
  310.       if (standardEncoding[i]) {
  311.         encoding[i] = copyString(standardEncoding[i]);
  312.       }
  313.     }
  314.   } else if (enc == 1) {
  315.     for (i = 0; i < 256; ++i) {
  316.       if (expertEncoding[i]) {
  317.         encoding[i] = copyString(expertEncoding[i]);
  318.       }
  319.     }
  320.   } else {
  321.     ptr = (Guchar *)file + enc;
  322.     encFormat = *ptr++;
  323.     if ((encFormat & 0x7f) == 0) {
  324.       nCodes = 1 + *ptr++;
  325.       if (nCodes > nGlyphs) {
  326.         nCodes = nGlyphs;
  327.       }
  328.       for (i = 1; i < nCodes; ++i) {
  329.         c = *ptr++;
  330.         encoding[c] = copyString(getString(glyphNames[i], buf));
  331.       }
  332.     } else if ((encFormat & 0x7f) == 1) {
  333.       nRanges = *ptr++;
  334.       nCodes = 1;
  335.       for (i = 0; i < nRanges; ++i) {
  336.         c = *ptr++;
  337.         nLeft = *ptr++;
  338.         for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
  339.           encoding[c] = copyString(getString(glyphNames[nCodes], buf));
  340.           ++nCodes;
  341.           ++c;
  342.         }
  343.       }
  344.     }
  345.     if (encFormat & 0x80) {
  346.       nSups = *ptr++;
  347.       for (i = 0; i < nSups; ++i) {
  348.         c = *ptr++;
  349.         sid = getWord(ptr, 2);
  350.         ptr += 2;
  351.         encoding[c] = copyString(getString(sid, buf));
  352.       }
  353.     }
  354.   }
  355.  
  356.   if (charset > 2) {
  357.     gfree(glyphNames);
  358.   }
  359. }
  360.  
  361. void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
  362.                                     void *outputStreamA) {
  363.   Type1CTopDict dict;
  364.   Type1CPrivateDict privateDict;
  365.   char buf[512], eBuf[256];
  366.   Guchar *idxPtr0, *idxPtr1, *subrsIdxPtr, *charStringsIdxPtr, *ptr;
  367.   int nGlyphs, nCodes, nRanges, nLeft, nSups;
  368.   Gushort *glyphNames;
  369.   int encFormat, nSubrs, nCharStrings;
  370.   int c, sid;
  371.   int i, j, n;
  372.  
  373.   outputFunc = outputFuncA;
  374.   outputStream = outputStreamA;
  375.  
  376.   // read top dict (first font only)
  377.   readTopDict(&dict);
  378.  
  379.   // get global subrs
  380.   //~ ... global subrs are unimplemented
  381.  
  382.   // write header and font dictionary, up to encoding
  383.   (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
  384.   (*outputFunc)(outputStream, name->getCString(), name->getLength());
  385.   if (dict.version != 0) {
  386.     getString(dict.version, buf);
  387.     (*outputFunc)(outputStream, buf, strlen(buf));
  388.   }
  389.   (*outputFunc)(outputStream, "\n", 1);
  390.   (*outputFunc)(outputStream, "11 dict begin\n", 14);
  391.   (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
  392.   if (dict.version != 0) {
  393.     (*outputFunc)(outputStream, "/version (", 10);
  394.     (*outputFunc)(outputStream, buf, strlen(buf));
  395.     (*outputFunc)(outputStream, ") readonly def\n", 15);
  396.   }
  397.   if (dict.notice != 0) {
  398.     getString(dict.notice, buf);
  399.     (*outputFunc)(outputStream, "/Notice (", 9);
  400.     (*outputFunc)(outputStream, buf, strlen(buf));
  401.     (*outputFunc)(outputStream, ") readonly def\n", 15);
  402.   }
  403.   if (dict.copyright != 0) {
  404.     getString(dict.copyright, buf);
  405.     (*outputFunc)(outputStream, "/Copyright (", 12);
  406.     (*outputFunc)(outputStream, buf, strlen(buf));
  407.     (*outputFunc)(outputStream, ") readonly def\n", 15);
  408.   }
  409.   if (dict.fullName != 0) {
  410.     getString(dict.fullName, buf);
  411.     (*outputFunc)(outputStream, "/FullName (", 11);
  412.     (*outputFunc)(outputStream, buf, strlen(buf));
  413.     (*outputFunc)(outputStream, ") readonly def\n", 15);
  414.   }
  415.   if (dict.familyName != 0) {
  416.     getString(dict.familyName, buf);
  417.     (*outputFunc)(outputStream, "/FamilyName (", 13);
  418.     (*outputFunc)(outputStream, buf, strlen(buf));
  419.     (*outputFunc)(outputStream, ") readonly def\n", 15);
  420.   }
  421.   if (dict.weight != 0) {
  422.     getString(dict.weight, buf);
  423.     (*outputFunc)(outputStream, "/Weight (", 9);
  424.     (*outputFunc)(outputStream, buf, strlen(buf));
  425.     (*outputFunc)(outputStream, ") readonly def\n", 15);
  426.   }
  427.   if (dict.isFixedPitch) {
  428.     (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
  429.   } else {
  430.     (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
  431.   }
  432.   sprintf(buf, "/ItalicAngle %g def\n", dict.italicAngle);
  433.   (*outputFunc)(outputStream, buf, strlen(buf));
  434.   sprintf(buf, "/UnderlinePosition %g def\n", dict.underlinePosition);
  435.   (*outputFunc)(outputStream, buf, strlen(buf));
  436.   sprintf(buf, "/UnderlineThickness %g def\n", dict.underlineThickness);
  437.   (*outputFunc)(outputStream, buf, strlen(buf));
  438.   (*outputFunc)(outputStream, "end readonly def\n", 17);
  439.   (*outputFunc)(outputStream, "/FontName /", 11);
  440.   (*outputFunc)(outputStream, name->getCString(), name->getLength());
  441.   (*outputFunc)(outputStream, " def\n", 5);
  442.   sprintf(buf, "/PaintType %d def\n", dict.paintType);
  443.   (*outputFunc)(outputStream, buf, strlen(buf));
  444.   (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
  445.   sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
  446.           dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
  447.           dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
  448.   (*outputFunc)(outputStream, buf, strlen(buf));
  449.   sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
  450.           dict.fontBBox[0], dict.fontBBox[1],
  451.           dict.fontBBox[2], dict.fontBBox[3]);
  452.   (*outputFunc)(outputStream, buf, strlen(buf));
  453.   sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
  454.   (*outputFunc)(outputStream, buf, strlen(buf));
  455.   if (dict.uniqueID != 0) {
  456.     sprintf(buf, "/UniqueID %d def\n", dict.uniqueID);
  457.     (*outputFunc)(outputStream, buf, strlen(buf));
  458.   }
  459.  
  460.   // get number of glyphs from charstrings index
  461.   nGlyphs = getIndexLen((Guchar *)file + dict.charStrings);
  462.  
  463.   // read charset
  464.   glyphNames = readCharset(dict.charset, nGlyphs);
  465.  
  466.   // read encoding (glyph -> code mapping), write Type 1 encoding
  467.   (*outputFunc)(outputStream, "/Encoding ", 10);
  468.   if (dict.encoding == 0) {
  469.     (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
  470.   } else {
  471.     (*outputFunc)(outputStream, "256 array\n", 10);
  472.     (*outputFunc)(outputStream,
  473.                   "0 1 255 {1 index exch /.notdef put} for\n", 40);
  474.     if (dict.encoding == 1) {
  475.       for (i = 0; i < 256; ++i) {
  476.         if (expertEncoding[i]) {
  477.           sprintf(buf, "dup %d /%s put\n", i, expertEncoding[i]);
  478.           (*outputFunc)(outputStream, buf, strlen(buf));
  479.         }
  480.       }
  481.     } else {
  482.       ptr = (Guchar *)file + dict.encoding;
  483.       encFormat = *ptr++;
  484.       if ((encFormat & 0x7f) == 0) {
  485.         nCodes = 1 + *ptr++;
  486.         if (nCodes > nGlyphs) {
  487.           nCodes = nGlyphs;
  488.         }
  489.         for (i = 1; i < nCodes; ++i) {
  490.           c = *ptr++;
  491.           sprintf(buf, "dup %d /", c);
  492.           (*outputFunc)(outputStream, buf, strlen(buf));
  493.           getString(glyphNames[i], buf);
  494.           (*outputFunc)(outputStream, buf, strlen(buf));
  495.           (*outputFunc)(outputStream, " put\n", 5);
  496.         }
  497.       } else if ((encFormat & 0x7f) == 1) {
  498.         nRanges = *ptr++;
  499.         nCodes = 1;
  500.         for (i = 0; i < nRanges; ++i) {
  501.           c = *ptr++;
  502.           nLeft = *ptr++;
  503.           for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
  504.             sprintf(buf, "dup %d /", c);
  505.             (*outputFunc)(outputStream, buf, strlen(buf));
  506.             getString(glyphNames[nCodes], buf);
  507.             (*outputFunc)(outputStream, buf, strlen(buf));
  508.             (*outputFunc)(outputStream, " put\n", 5);
  509.             ++nCodes;
  510.             ++c;
  511.           }
  512.         }
  513.       }
  514.       if (encFormat & 0x80) {
  515.         nSups = *ptr++;
  516.         for (i = 0; i < nSups; ++i) {
  517.           c = *ptr++;
  518.           sid = getWord(ptr, 2);
  519.           ptr += 2;
  520.           sprintf(buf, "dup %d /", c);
  521.           (*outputFunc)(outputStream, buf, strlen(buf));
  522.           getString(sid, buf);
  523.           (*outputFunc)(outputStream, buf, strlen(buf));
  524.           (*outputFunc)(outputStream, " put\n", 5);
  525.         }
  526.       }
  527.     }
  528.     (*outputFunc)(outputStream, "readonly def\n", 13);
  529.   }
  530.   (*outputFunc)(outputStream, "currentdict end\n", 16);
  531.  
  532.   // start the binary section
  533.   (*outputFunc)(outputStream, "currentfile eexec\n", 18);
  534.   r1 = 55665;
  535.   line = 0;
  536.  
  537.   // get private dictionary
  538.   eexecWrite("\x83\xca\x73\xd5");
  539.   eexecWrite("dup /Private 32 dict dup begin\n");
  540.   eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
  541.   eexecWrite("/ND {noaccess def} executeonly def\n");
  542.   eexecWrite("/NP {noaccess put} executeonly def\n");
  543.   eexecWrite("/MinFeature {16 16} ND\n");
  544.   readPrivateDict(&privateDict, dict.privateOffset, dict.privateSize);
  545.   eexecWrite(privateDict.dictData->getCString());
  546.   defaultWidthX = privateDict.defaultWidthX;
  547.   defaultWidthXFP = privateDict.defaultWidthXFP;
  548.   nominalWidthX = privateDict.nominalWidthX;
  549.   nominalWidthXFP = privateDict.nominalWidthXFP;
  550.  
  551.   // get subrs
  552.   if (privateDict.subrsOffset != 0) {
  553.     subrsIdxPtr = (Guchar *)file + dict.privateOffset +
  554.                   privateDict.subrsOffset;
  555.     nSubrs = getIndexLen(subrsIdxPtr);
  556.     sprintf(eBuf, "/Subrs %d array\n", nSubrs);
  557.     eexecWrite(eBuf);
  558.     idxPtr1 = getIndexValPtr(subrsIdxPtr, 0);
  559.     for (i = 0; i < nSubrs; ++i) {
  560.       idxPtr0 = idxPtr1;
  561.       idxPtr1 = getIndexValPtr(subrsIdxPtr, i+1);
  562.       n = idxPtr1 - idxPtr0;
  563. #if 1 //~ Type 2 subrs are unimplemented
  564.       error(-1, "Unimplemented Type 2 subrs");
  565. #else
  566.       sprintf(eBuf, "dup %d %d RD ", i, n);
  567.       eexecWrite(eBuf);
  568.       eexecCvtGlyph(idxPtr0, n);
  569.       eexecWrite(" NP\n");
  570. #endif
  571.     }
  572.     eexecWrite("ND\n");
  573.   }
  574.  
  575.   // get CharStrings
  576.   charStringsIdxPtr = (Guchar *)file + dict.charStrings;
  577.   nCharStrings = getIndexLen(charStringsIdxPtr);
  578.   sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings);
  579.   eexecWrite(eBuf);
  580.   idxPtr1 = getIndexValPtr(charStringsIdxPtr, 0);
  581.   for (i = 0; i < nCharStrings; ++i) {
  582.     idxPtr0 = idxPtr1;
  583.     idxPtr1 = getIndexValPtr(charStringsIdxPtr, i+1);
  584.     n = idxPtr1 - idxPtr0;
  585.     eexecCvtGlyph(getString(glyphNames[i], buf), idxPtr0, n);
  586.   }
  587.   eexecWrite("end\n");
  588.   eexecWrite("end\n");
  589.   eexecWrite("readonly put\n");
  590.   eexecWrite("noaccess put\n");
  591.   eexecWrite("dup /FontName get exch definefont pop\n");
  592.   eexecWrite("mark currentfile closefile\n");
  593.  
  594.   // trailer
  595.   if (line > 0) {
  596.     (*outputFunc)(outputStream, "\n", 1);
  597.   }
  598.   for (i = 0; i < 8; ++i) {
  599.     (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
  600.   }
  601.   (*outputFunc)(outputStream, "cleartomark\n", 12);
  602.  
  603.   // clean up
  604.   delete privateDict.dictData;
  605.   if (dict.charset > 2) {
  606.     gfree(glyphNames);
  607.   }
  608. }
  609.  
  610. void Type1CFontFile::convertToCIDType0(char *psName,
  611.                                        FontFileOutputFunc outputFuncA,
  612.                                        void *outputStreamA) {
  613.   Type1CTopDict dict;
  614.   Type1CPrivateDict *privateDicts;
  615.   GString *charStrings;
  616.   int *charStringOffsets;
  617.   Gushort *charset;
  618.   int *cidMap;
  619.   Guchar *fdSelect;
  620.   Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
  621.   char buf[512], buf2[16];
  622.   int nGlyphs, nCIDs, gdBytes, nFDs;
  623.   int fdSelectFmt, nRanges, gid0, gid1, fd, offset;
  624.   int key;
  625.   double x;
  626.   GBool isFP;
  627.   int i, j, k, n;
  628.  
  629.   outputFunc = outputFuncA;
  630.   outputStream = outputStreamA;
  631.  
  632.   (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
  633.  
  634.   // read top dict (first font only)
  635.   readTopDict(&dict);
  636.  
  637.   // read the FDArray dictionaries and Private dictionaries
  638.   if (dict.fdArrayOffset == 0) {
  639.     nFDs = 1;
  640.     privateDicts = (Type1CPrivateDict *)
  641.                      gmalloc(nFDs * sizeof(Type1CPrivateDict));
  642.     privateDicts[0].dictData = new GString();
  643.     privateDicts[0].subrsOffset = 0;
  644.     privateDicts[0].defaultWidthX = 0;
  645.     privateDicts[0].defaultWidthXFP = gFalse;
  646.     privateDicts[0].nominalWidthX = 0;
  647.     privateDicts[0].nominalWidthXFP = gFalse;
  648.   } else {
  649.     fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
  650.     nFDs = getIndexLen(fdArrayIdx);
  651.     privateDicts = (Type1CPrivateDict *)
  652.                      gmalloc(nFDs * sizeof(Type1CPrivateDict));
  653.     idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
  654.     for (i = 0; i < nFDs; ++i) {
  655.       privateDicts[i].dictData = NULL;
  656.       idxPtr0 = idxPtr1;
  657.       idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
  658.       ptr = idxPtr0;
  659.       j = 0;
  660.       while (ptr < idxPtr1) {
  661.         if (*ptr <= 27 || *ptr == 31) {
  662.           key = *ptr++;
  663.           if (key == 0x0c) {
  664.             key = (key << 8) | *ptr++;
  665.           }
  666.           if (key == 0x0012) {
  667.             readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
  668.           }
  669.           j = 0;
  670.         } else {
  671.           x = getNum(&ptr, &isFP);
  672.           if (j < 48) {
  673.             op[j] = x;
  674.             fp[j++] = isFP;
  675.           }
  676.         }
  677.       }
  678.       if (!privateDicts[i].dictData) {
  679.         privateDicts[i].dictData = new GString();
  680.         privateDicts[i].subrsOffset = 0;
  681.         privateDicts[i].defaultWidthX = 0;
  682.         privateDicts[i].defaultWidthXFP = gFalse;
  683.         privateDicts[i].nominalWidthX = 0;
  684.         privateDicts[i].nominalWidthXFP = gFalse;
  685.       }
  686.     }
  687.   }
  688.  
  689.   // get the glyph count
  690.   charStringsIdxPtr = (Guchar *)file + dict.charStrings;
  691.   nGlyphs = getIndexLen(charStringsIdxPtr);
  692.  
  693.   // read the FDSelect table
  694.   fdSelect = (Guchar *)gmalloc(nGlyphs);
  695.   if (dict.fdSelectOffset == 0) {
  696.     for (i = 0; i < nGlyphs; ++i) {
  697.       fdSelect[i] = 0;
  698.     }
  699.   } else {
  700.     ptr = (Guchar *)file + dict.fdSelectOffset;
  701.     fdSelectFmt = *ptr++;
  702.     if (fdSelectFmt == 0) {
  703.       memcpy(fdSelect, ptr, nGlyphs);
  704.     } else if (fdSelectFmt == 3) {
  705.       nRanges = getWord(ptr, 2);
  706.       ptr += 2;
  707.       gid0 = getWord(ptr, 2);
  708.       ptr += 2;
  709.       for (i = 1; i <= nRanges; ++i) {
  710.         fd = *ptr++;
  711.         gid1 = getWord(ptr, 2);
  712.         ptr += 2;
  713.         for (j = gid0; j < gid1; ++j) {
  714.           fdSelect[j] = fd;
  715.         }
  716.         gid0 = gid1;
  717.       }
  718.     } else {
  719.       error(-1, "Unknown FDSelect table format in CID font");
  720.       for (i = 0; i < nGlyphs; ++i) {
  721.         fdSelect[i] = 0;
  722.       }
  723.     }
  724.   }
  725.  
  726.   // read the charset, compute the CID-to-GID mapping
  727.   charset = readCharset(dict.charset, nGlyphs);
  728.   nCIDs = 0;
  729.   for (i = 0; i < nGlyphs; ++i) {
  730.     if (charset[i] >= nCIDs) {
  731.       nCIDs = charset[i] + 1;
  732.     }
  733.   }
  734.   cidMap = (int *)gmalloc(nCIDs * sizeof(int));
  735.   for (i = 0; i < nCIDs; ++i) {
  736.     cidMap[i] = -1;
  737.   }
  738.   for (i = 0; i < nGlyphs; ++i) {
  739.     cidMap[charset[i]] = i;
  740.   }
  741.  
  742.   // build the charstrings
  743.   charStrings = new GString();
  744.   charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
  745.   for (i = 0; i < nCIDs; ++i) {
  746.     charStringOffsets[i] = charStrings->getLength();
  747.     if (cidMap[i] >= 0) {
  748.       idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i]);
  749.       idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i]+1);
  750.       n = idxPtr1 - idxPtr0;
  751.       j = fdSelect[cidMap[i]];
  752.       defaultWidthX = privateDicts[j].defaultWidthX;
  753.       defaultWidthXFP = privateDicts[j].defaultWidthXFP;
  754.       nominalWidthX = privateDicts[j].nominalWidthX;
  755.       nominalWidthXFP = privateDicts[j].nominalWidthXFP;
  756.       cvtGlyph(idxPtr0, n);
  757.       charStrings->append(charBuf);
  758.       delete charBuf;
  759.     }
  760.   }
  761.   charStringOffsets[nCIDs] = charStrings->getLength();
  762.  
  763.   // compute gdBytes = number of bytes needed for charstring offsets
  764.   // (offset size needs to account for the charstring offset table,
  765.   // with a worst case of five bytes per entry, plus the charstrings
  766.   // themselves)
  767.   i = (nCIDs + 1) * 5 + charStrings->getLength();
  768.   if (i < 0x100) {
  769.     gdBytes = 1;
  770.   } else if (i < 0x10000) {
  771.     gdBytes = 2;
  772.   } else if (i < 0x1000000) {
  773.     gdBytes = 3;
  774.   } else {
  775.     gdBytes = 4;
  776.   }
  777.  
  778.   // begin the font dictionary
  779.   (*outputFunc)(outputStream, "20 dict begin\n", 14);
  780.   (*outputFunc)(outputStream, "/CIDFontName /", 14);
  781.   (*outputFunc)(outputStream, psName, strlen(psName));
  782.   (*outputFunc)(outputStream, " def\n", 5);
  783.   (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
  784.   (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
  785.   if (dict.registry > 0 && dict.ordering > 0) {
  786.     getString(dict.registry, buf);
  787.     (*outputFunc)(outputStream, "  /Registry (", 13);
  788.     (*outputFunc)(outputStream, buf, strlen(buf));
  789.     (*outputFunc)(outputStream, ") def\n", 6);
  790.     getString(dict.ordering, buf);
  791.     (*outputFunc)(outputStream, "  /Ordering (", 13);
  792.     (*outputFunc)(outputStream, buf, strlen(buf));
  793.     (*outputFunc)(outputStream, ") def\n", 6);
  794.   } else {
  795.     (*outputFunc)(outputStream, "  /Registry (Adobe) def\n", 24);
  796.     (*outputFunc)(outputStream, "  /Ordering (Identity) def\n", 27);
  797.   }
  798.   sprintf(buf, "  /Supplement %d def\n", dict.supplement);
  799.   (*outputFunc)(outputStream, buf, strlen(buf));
  800.   (*outputFunc)(outputStream, "end def\n", 8);
  801.   sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
  802.           dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
  803.           dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
  804.   (*outputFunc)(outputStream, buf, strlen(buf));
  805.   sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
  806.           dict.fontBBox[0], dict.fontBBox[1],
  807.           dict.fontBBox[2], dict.fontBBox[3]);
  808.   (*outputFunc)(outputStream, buf, strlen(buf));
  809.   (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
  810.   (*outputFunc)(outputStream, "  /FSType 8 def\n", 16);
  811.   (*outputFunc)(outputStream, "end def\n", 8);
  812.  
  813.   // CIDFont-specific entries
  814.   sprintf(buf, "/CIDCount %d def\n", nCIDs);
  815.   (*outputFunc)(outputStream, buf, strlen(buf));
  816.   (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
  817.   sprintf(buf, "/GDBytes %d def\n", gdBytes);
  818.   (*outputFunc)(outputStream, buf, strlen(buf));
  819.   (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
  820.   if (dict.paintType != 0) {
  821.     sprintf(buf, "/PaintType %d def\n", dict.paintType);
  822.     (*outputFunc)(outputStream, buf, strlen(buf));
  823.     sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
  824.     (*outputFunc)(outputStream, buf, strlen(buf));
  825.   }
  826.  
  827.   // FDArray entry
  828.   sprintf(buf, "/FDArray %d array\n", nFDs);
  829.   (*outputFunc)(outputStream, buf, strlen(buf));
  830.   for (i = 0; i < nFDs; ++i) {
  831.     sprintf(buf, "dup %d 10 dict begin\n", i);
  832.     (*outputFunc)(outputStream, buf, strlen(buf));
  833.     (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
  834.     (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
  835.     sprintf(buf, "/PaintType %d def\n", dict.paintType);
  836.     (*outputFunc)(outputStream, buf, strlen(buf));
  837.     (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
  838.     (*outputFunc)(outputStream, privateDicts[i].dictData->getCString(),
  839.                   privateDicts[i].dictData->getLength());
  840.     (*outputFunc)(outputStream, "currentdict end def\n", 20);
  841.     (*outputFunc)(outputStream, "currentdict end put\n", 20);
  842.   }
  843.   (*outputFunc)(outputStream, "def\n", 4);
  844.  
  845.   //~ need to deal with subrs
  846.   
  847.   // start the binary section
  848.   offset = (nCIDs + 1) * (1 + gdBytes);
  849.   sprintf(buf, "(Hex) %d StartData\n",
  850.           offset + charStrings->getLength());
  851.   (*outputFunc)(outputStream, buf, strlen(buf));
  852.  
  853.   // write the charstring offset (CIDMap) table
  854.   for (i = 0; i <= nCIDs; i += 6) {
  855.     for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
  856.       if (i+j < nCIDs && cidMap[i+j] >= 0) {
  857.         buf[0] = (char)fdSelect[cidMap[i+j]];
  858.       } else {
  859.         buf[0] = (char)0;
  860.       }
  861.       n = offset + charStringOffsets[i+j];
  862.       for (k = gdBytes; k >= 1; --k) {
  863.         buf[k] = (char)(n & 0xff);
  864.         n >>= 8;
  865.       }
  866.       for (k = 0; k <= gdBytes; ++k) {
  867.         sprintf(buf2, "%02x", buf[k] & 0xff);
  868.         (*outputFunc)(outputStream, buf2, 2);
  869.       }
  870.     }
  871.     (*outputFunc)(outputStream, "\n", 1);
  872.   }
  873.  
  874.   // write the charstring data
  875.   n = charStrings->getLength();
  876.   for (i = 0; i < n; i += 32) {
  877.     for (j = 0; j < 32 && i+j < n; ++j) {
  878.       sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff);
  879.       (*outputFunc)(outputStream, buf, strlen(buf));
  880.     }
  881.     if (i + 32 >= n) {
  882.       (*outputFunc)(outputStream, ">", 1);
  883.     }
  884.     (*outputFunc)(outputStream, "\n", 1);
  885.   }
  886.  
  887.   for (i = 0; i < nFDs; ++i) {
  888.     delete privateDicts[i].dictData;
  889.   }
  890.   gfree(privateDicts);
  891.   gfree(cidMap);
  892.   gfree(charset);
  893.   gfree(charStringOffsets);
  894.   delete charStrings;
  895.   gfree(fdSelect);
  896. }
  897.  
  898. void Type1CFontFile::convertToType0(char *psName,
  899.                                     FontFileOutputFunc outputFuncA,
  900.                                     void *outputStreamA) {
  901.   Type1CTopDict dict;
  902.   Type1CPrivateDict *privateDicts;
  903.   Gushort *charset;
  904.   int *cidMap;
  905.   Guchar *fdSelect;
  906.   Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
  907.   char buf[512];
  908.   char eBuf[256];
  909.   int nGlyphs, nCIDs, nFDs;
  910.   int fdSelectFmt, nRanges, gid0, gid1, fd;
  911.   int key;
  912.   double x;
  913.   GBool isFP;
  914.   int i, j, n;
  915.  
  916.   outputFunc = outputFuncA;
  917.   outputStream = outputStreamA;
  918.  
  919.   // read top dict (first font only)
  920.   readTopDict(&dict);
  921.  
  922.   // read the FDArray dictionaries and Private dictionaries
  923.   if (dict.fdArrayOffset == 0) {
  924.     nFDs = 1;
  925.     privateDicts = (Type1CPrivateDict *)
  926.                      gmalloc(nFDs * sizeof(Type1CPrivateDict));
  927.     privateDicts[0].dictData = new GString();
  928.     privateDicts[0].subrsOffset = 0;
  929.     privateDicts[0].defaultWidthX = 0;
  930.     privateDicts[0].defaultWidthXFP = gFalse;
  931.     privateDicts[0].nominalWidthX = 0;
  932.     privateDicts[0].nominalWidthXFP = gFalse;
  933.   } else {
  934.     fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
  935.     nFDs = getIndexLen(fdArrayIdx);
  936.     privateDicts = (Type1CPrivateDict *)
  937.                      gmalloc(nFDs * sizeof(Type1CPrivateDict));
  938.     idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
  939.     for (i = 0; i < nFDs; ++i) {
  940.       privateDicts[i].dictData = NULL;
  941.       idxPtr0 = idxPtr1;
  942.       idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
  943.       ptr = idxPtr0;
  944.       j = 0;
  945.       while (ptr < idxPtr1) {
  946.         if (*ptr <= 27 || *ptr == 31) {
  947.           key = *ptr++;
  948.           if (key == 0x0c) {
  949.             key = (key << 8) | *ptr++;
  950.           }
  951.           if (key == 0x0012) {
  952.             readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
  953.           }
  954.           j = 0;
  955.         } else {
  956.           x = getNum(&ptr, &isFP);
  957.           if (j < 48) {
  958.             op[j] = x;
  959.             fp[j++] = isFP;
  960.           }
  961.         }
  962.       }
  963.       if (!privateDicts[i].dictData) {
  964.         privateDicts[i].dictData = new GString();
  965.         privateDicts[i].subrsOffset = 0;
  966.         privateDicts[i].defaultWidthX = 0;
  967.         privateDicts[i].defaultWidthXFP = gFalse;
  968.         privateDicts[i].nominalWidthX = 0;
  969.         privateDicts[i].nominalWidthXFP = gFalse;
  970.       }
  971.     }
  972.   }
  973.  
  974.   // get the glyph count
  975.   charStringsIdxPtr = (Guchar *)file + dict.charStrings;
  976.   nGlyphs = getIndexLen(charStringsIdxPtr);
  977.  
  978.   // read the FDSelect table
  979.   fdSelect = (Guchar *)gmalloc(nGlyphs);
  980.   if (dict.fdSelectOffset == 0) {
  981.     for (i = 0; i < nGlyphs; ++i) {
  982.       fdSelect[i] = 0;
  983.     }
  984.   } else {
  985.     ptr = (Guchar *)file + dict.fdSelectOffset;
  986.     fdSelectFmt = *ptr++;
  987.     if (fdSelectFmt == 0) {
  988.       memcpy(fdSelect, ptr, nGlyphs);
  989.     } else if (fdSelectFmt == 3) {
  990.       nRanges = getWord(ptr, 2);
  991.       ptr += 2;
  992.       gid0 = getWord(ptr, 2);
  993.       ptr += 2;
  994.       for (i = 1; i <= nRanges; ++i) {
  995.         fd = *ptr++;
  996.         gid1 = getWord(ptr, 2);
  997.         ptr += 2;
  998.         for (j = gid0; j < gid1; ++j) {
  999.           fdSelect[j] = fd;
  1000.         }
  1001.         gid0 = gid1;
  1002.       }
  1003.     } else {
  1004.       error(-1, "Unknown FDSelect table format in CID font");
  1005.       for (i = 0; i < nGlyphs; ++i) {
  1006.         fdSelect[i] = 0;
  1007.       }
  1008.     }
  1009.   }
  1010.  
  1011.   // read the charset, compute the CID-to-GID mapping
  1012.   charset = readCharset(dict.charset, nGlyphs);
  1013.   nCIDs = 0;
  1014.   for (i = 0; i < nGlyphs; ++i) {
  1015.     if (charset[i] >= nCIDs) {
  1016.       nCIDs = charset[i] + 1;
  1017.     }
  1018.   }
  1019.   cidMap = (int *)gmalloc(nCIDs * sizeof(int));
  1020.   for (i = 0; i < nCIDs; ++i) {
  1021.     cidMap[i] = -1;
  1022.   }
  1023.   for (i = 0; i < nGlyphs; ++i) {
  1024.     cidMap[charset[i]] = i;
  1025.   }
  1026.  
  1027.   // write the descendant Type 1 fonts
  1028.   for (i = 0; i < nCIDs; i += 256) {
  1029.  
  1030.     //~ this assumes that all CIDs in this block have the same FD --
  1031.     //~ to handle multiple FDs correctly, need to somehow divide the
  1032.     //~ font up by FD
  1033.     fd = 0;
  1034.     for (j = 0; j < 256 && i+j < nCIDs; ++j) {
  1035.       if (cidMap[i+j] >= 0) {
  1036.         fd = fdSelect[cidMap[i+j]];
  1037.         break;
  1038.       }
  1039.     }
  1040.  
  1041.     // font dictionary (unencrypted section)
  1042.     (*outputFunc)(outputStream, "16 dict begin\n", 14);
  1043.     (*outputFunc)(outputStream, "/FontName /", 11);
  1044.     (*outputFunc)(outputStream, psName, strlen(psName));
  1045.     sprintf(buf, "_%02x def\n", i >> 8);
  1046.     (*outputFunc)(outputStream, buf, strlen(buf));
  1047.     (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
  1048.     sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
  1049.             dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
  1050.             dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
  1051.     (*outputFunc)(outputStream, buf, strlen(buf));
  1052.     sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
  1053.             dict.fontBBox[0], dict.fontBBox[1],
  1054.             dict.fontBBox[2], dict.fontBBox[3]);
  1055.     (*outputFunc)(outputStream, buf, strlen(buf));
  1056.     sprintf(buf, "/PaintType %d def\n", dict.paintType);
  1057.     (*outputFunc)(outputStream, buf, strlen(buf));
  1058.     if (dict.paintType != 0) {
  1059.       sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
  1060.       (*outputFunc)(outputStream, buf, strlen(buf));
  1061.     }
  1062.     (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
  1063.     for (j = 0; j < 256 && i+j < nCIDs; ++j) {
  1064.       sprintf(buf, "dup %d /c%02x put\n", j, j);
  1065.       (*outputFunc)(outputStream, buf, strlen(buf));
  1066.     }
  1067.     (*outputFunc)(outputStream, "readonly def\n", 13);
  1068.     (*outputFunc)(outputStream, "currentdict end\n", 16);
  1069.  
  1070.     // start the binary section
  1071.     (*outputFunc)(outputStream, "currentfile eexec\n", 18);
  1072.     r1 = 55665;
  1073.     line = 0;
  1074.  
  1075.     // start the private dictionary
  1076.     eexecWrite("\x83\xca\x73\xd5");
  1077.     eexecWrite("dup /Private 32 dict dup begin\n");
  1078.     eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
  1079.     eexecWrite("/ND {noaccess def} executeonly def\n");
  1080.     eexecWrite("/NP {noaccess put} executeonly def\n");
  1081.     eexecWrite("/MinFeature {16 16} ND\n");
  1082.     eexecWrite(privateDicts[fd].dictData->getCString());
  1083.     defaultWidthX = privateDicts[fd].defaultWidthX;
  1084.     defaultWidthXFP = privateDicts[fd].defaultWidthXFP;
  1085.     nominalWidthX = privateDicts[fd].nominalWidthX;
  1086.     nominalWidthXFP = privateDicts[fd].nominalWidthXFP;
  1087.  
  1088.     // start the CharStrings
  1089.     sprintf(eBuf, "2 index /CharStrings 256 dict dup begin\n");
  1090.     eexecWrite(eBuf);
  1091.  
  1092.     // write the .notdef CharString
  1093.     idxPtr0 = getIndexValPtr(charStringsIdxPtr, 0);
  1094.     idxPtr1 = getIndexValPtr(charStringsIdxPtr, 1);
  1095.     n = idxPtr1 - idxPtr0;
  1096.     eexecCvtGlyph(".notdef", idxPtr0, n);
  1097.  
  1098.     // write the CharStrings
  1099.     for (j = 0; j < 256 && i+j < nCIDs; ++j) {
  1100.       if (cidMap[i+j] >= 0) {
  1101.         idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]);
  1102.         idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]+1);
  1103.         n = idxPtr1 - idxPtr0;
  1104.         sprintf(buf, "c%02x", j);
  1105.         eexecCvtGlyph(buf, idxPtr0, n);
  1106.       }
  1107.     }
  1108.     eexecWrite("end\n");
  1109.     eexecWrite("end\n");
  1110.     eexecWrite("readonly put\n");
  1111.     eexecWrite("noaccess put\n");
  1112.     eexecWrite("dup /FontName get exch definefont pop\n");
  1113.     eexecWrite("mark currentfile closefile\n");
  1114.  
  1115.     // trailer
  1116.     if (line > 0) {
  1117.       (*outputFunc)(outputStream, "\n", 1);
  1118.     }
  1119.     for (j = 0; j < 8; ++j) {
  1120.       (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
  1121.     }
  1122.     (*outputFunc)(outputStream, "cleartomark\n", 12);
  1123.   }
  1124.  
  1125.   // write the Type 0 parent font
  1126.   (*outputFunc)(outputStream, "16 dict begin\n", 14);
  1127.   (*outputFunc)(outputStream, "/FontName /", 11);
  1128.   (*outputFunc)(outputStream, psName, strlen(psName));
  1129.   (*outputFunc)(outputStream, " def\n", 5);
  1130.   (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
  1131.   (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
  1132.   (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
  1133.   (*outputFunc)(outputStream, "/Encoding [\n", 12);
  1134.   for (i = 0; i < nCIDs; i += 256) {
  1135.     sprintf(buf, "%d\n", i >> 8);
  1136.     (*outputFunc)(outputStream, buf, strlen(buf));
  1137.   }
  1138.   (*outputFunc)(outputStream, "] def\n", 6);
  1139.   (*outputFunc)(outputStream, "/FDepVector [\n", 14);
  1140.   for (i = 0; i < nCIDs; i += 256) {
  1141.     (*outputFunc)(outputStream, "/", 1);
  1142.     (*outputFunc)(outputStream, psName, strlen(psName));
  1143.     sprintf(buf, "_%02x findfont\n", i >> 8);
  1144.     (*outputFunc)(outputStream, buf, strlen(buf));
  1145.   }
  1146.   (*outputFunc)(outputStream, "] def\n", 6);
  1147.   (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
  1148.  
  1149.   // clean up
  1150.   for (i = 0; i < nFDs; ++i) {
  1151.     delete privateDicts[i].dictData;
  1152.   }
  1153.   gfree(privateDicts);
  1154.   gfree(cidMap);
  1155.   gfree(charset);
  1156.   gfree(fdSelect);
  1157. }
  1158.  
  1159. void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
  1160.   Guchar *idxPtr0, *idxPtr1, *ptr;
  1161.   double x;
  1162.   GBool isFP;
  1163.   int key;
  1164.   int i;
  1165.  
  1166.   idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
  1167.   idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
  1168.   dict->version = 0;
  1169.   dict->notice = 0;
  1170.   dict->copyright = 0;
  1171.   dict->fullName = 0;
  1172.   dict->familyName = 0;
  1173.   dict->weight = 0;
  1174.   dict->isFixedPitch = 0;
  1175.   dict->italicAngle = 0;
  1176.   dict->underlinePosition = -100;
  1177.   dict->underlineThickness = 50;
  1178.   dict->paintType = 0;
  1179.   dict->charstringType = 2;
  1180.   dict->fontMatrix[0] = 0.001;
  1181.   dict->fontMatrix[1] = 0;
  1182.   dict->fontMatrix[2] = 0;
  1183.   dict->fontMatrix[3] = 0.001;
  1184.   dict->fontMatrix[4] = 0;
  1185.   dict->fontMatrix[5] = 0;
  1186.   dict->uniqueID = 0;
  1187.   dict->fontBBox[0] = 0;
  1188.   dict->fontBBox[1] = 0;
  1189.   dict->fontBBox[2] = 0;
  1190.   dict->fontBBox[3] = 0;
  1191.   dict->strokeWidth = 0;
  1192.   dict->charset = 0;
  1193.   dict->encoding = 0;
  1194.   dict->charStrings = 0;
  1195.   dict->privateSize = 0;
  1196.   dict->privateOffset = 0;
  1197.   dict->registry = 0;
  1198.   dict->ordering = 0;
  1199.   dict->supplement = 0;
  1200.   dict->fdArrayOffset = 0;
  1201.   dict->fdSelectOffset = 0;
  1202.   i = 0;
  1203.   ptr = idxPtr0;
  1204.   while (ptr < idxPtr1) {
  1205.     if (*ptr <= 27 || *ptr == 31) {
  1206.       key = *ptr++;
  1207.       if (key == 0x0c) {
  1208.         key = (key << 8) | *ptr++;
  1209.       }
  1210.       switch (key) {
  1211.       case 0x0000: dict->version = (int)op[0]; break;
  1212.       case 0x0001: dict->notice = (int)op[0]; break;
  1213.       case 0x0c00: dict->copyright = (int)op[0]; break;
  1214.       case 0x0002: dict->fullName = (int)op[0]; break;
  1215.       case 0x0003: dict->familyName = (int)op[0]; break;
  1216.       case 0x0004: dict->weight = (int)op[0]; break;
  1217.       case 0x0c01: dict->isFixedPitch = (int)op[0]; break;
  1218.       case 0x0c02: dict->italicAngle = op[0]; break;
  1219.       case 0x0c03: dict->underlinePosition = op[0]; break;
  1220.       case 0x0c04: dict->underlineThickness = op[0]; break;
  1221.       case 0x0c05: dict->paintType = (int)op[0]; break;
  1222.       case 0x0c06: dict->charstringType = (int)op[0]; break;
  1223.       case 0x0c07: dict->fontMatrix[0] = op[0];
  1224.                    dict->fontMatrix[1] = op[1];
  1225.                    dict->fontMatrix[2] = op[2];
  1226.                    dict->fontMatrix[3] = op[3];
  1227.                    dict->fontMatrix[4] = op[4];
  1228.                    dict->fontMatrix[5] = op[5]; break;
  1229.       case 0x000d: dict->uniqueID = (int)op[0]; break;
  1230.       case 0x0005: dict->fontBBox[0] = op[0];
  1231.                    dict->fontBBox[1] = op[1];
  1232.                    dict->fontBBox[2] = op[2];
  1233.                    dict->fontBBox[3] = op[3]; break;
  1234.       case 0x0c08: dict->strokeWidth = op[0]; break;
  1235.       case 0x000f: dict->charset = (int)op[0]; break;
  1236.       case 0x0010: dict->encoding = (int)op[0]; break;
  1237.       case 0x0011: dict->charStrings = (int)op[0]; break;
  1238.       case 0x0012: dict->privateSize = (int)op[0];
  1239.                    dict->privateOffset = (int)op[1]; break;
  1240.       case 0x0c1e: dict->registry = (int)op[0];
  1241.                    dict->ordering = (int)op[1];
  1242.                    dict->supplement = (int)op[2]; break;
  1243.       case 0x0c24: dict->fdArrayOffset = (int)op[0]; break;
  1244.       case 0x0c25: dict->fdSelectOffset = (int)op[0]; break;
  1245.       }
  1246.       i = 0;
  1247.     } else {
  1248.       x = getNum(&ptr, &isFP);
  1249.       if (i < 48) {
  1250.         op[i] = x;
  1251.         fp[i++] = isFP;
  1252.       }
  1253.     }
  1254.   }
  1255. }
  1256.  
  1257. void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
  1258.                                      int offset, int size) {
  1259.   Guchar *idxPtr0, *idxPtr1, *ptr;
  1260.   char eBuf[256];
  1261.   int key;
  1262.   double x;
  1263.   GBool isFP;
  1264.   int i;
  1265.  
  1266.   privateDict->dictData = new GString();
  1267.   privateDict->subrsOffset = 0;
  1268.   privateDict->defaultWidthX = 0;
  1269.   privateDict->defaultWidthXFP = gFalse;
  1270.   privateDict->nominalWidthX = 0;
  1271.   privateDict->nominalWidthXFP = gFalse;
  1272.   idxPtr0 = (Guchar *)file + offset;
  1273.   idxPtr1 = idxPtr0 + size;
  1274.   ptr = idxPtr0;
  1275.   i = 0;
  1276.   while (ptr < idxPtr1) {
  1277.     if (*ptr <= 27 || *ptr == 31) {
  1278.       key = *ptr++;
  1279.       if (key == 0x0c) {
  1280.         key = (key << 8) | *ptr++;
  1281.       }
  1282.       switch (key) {
  1283.       case 0x0006:
  1284.         getDeltaInt(eBuf, "BlueValues", op, i);
  1285.         privateDict->dictData->append(eBuf);
  1286.         break;
  1287.       case 0x0007:
  1288.         getDeltaInt(eBuf, "OtherBlues", op, i);
  1289.         privateDict->dictData->append(eBuf);
  1290.         break;
  1291.       case 0x0008:
  1292.         getDeltaInt(eBuf, "FamilyBlues", op, i);
  1293.         privateDict->dictData->append(eBuf);
  1294.         break;
  1295.       case 0x0009:
  1296.         getDeltaInt(eBuf, "FamilyOtherBlues", op, i);
  1297.         privateDict->dictData->append(eBuf);
  1298.         break;
  1299.       case 0x0c09:
  1300.         sprintf(eBuf, "/BlueScale %g def\n", op[0]);
  1301.         privateDict->dictData->append(eBuf);
  1302.         break;
  1303.       case 0x0c0a:
  1304.         sprintf(eBuf, "/BlueShift %d def\n", (int)op[0]);
  1305.         privateDict->dictData->append(eBuf);
  1306.         break;
  1307.       case 0x0c0b:
  1308.         sprintf(eBuf, "/BlueFuzz %d def\n", (int)op[0]);
  1309.         privateDict->dictData->append(eBuf);
  1310.         break;
  1311.       case 0x000a:
  1312.         sprintf(eBuf, "/StdHW [%g] def\n", op[0]);
  1313.         privateDict->dictData->append(eBuf);
  1314.         break;
  1315.       case 0x000b:
  1316.         sprintf(eBuf, "/StdVW [%g] def\n", op[0]);
  1317.         privateDict->dictData->append(eBuf);
  1318.         break;
  1319.       case 0x0c0c:
  1320.         getDeltaReal(eBuf, "StemSnapH", op, i);
  1321.         privateDict->dictData->append(eBuf);
  1322.         break;
  1323.       case 0x0c0d:
  1324.         getDeltaReal(eBuf, "StemSnapV", op, i);
  1325.         privateDict->dictData->append(eBuf);
  1326.         break;
  1327.       case 0x0c0e:
  1328.         sprintf(eBuf, "/ForceBold %s def\n", op[0] ? "true" : "false");
  1329.         privateDict->dictData->append(eBuf);
  1330.         break;
  1331.       case 0x0c0f:
  1332.         sprintf(eBuf, "/ForceBoldThreshold %g def\n", op[0]);
  1333.         privateDict->dictData->append(eBuf);
  1334.         break;
  1335.       case 0x0c11:
  1336.         sprintf(eBuf, "/LanguageGroup %d def\n", (int)op[0]);
  1337.         privateDict->dictData->append(eBuf);
  1338.         break;
  1339.       case 0x0c12:
  1340.         sprintf(eBuf, "/ExpansionFactor %g def\n", op[0]);
  1341.         privateDict->dictData->append(eBuf);
  1342.         break;
  1343.       case 0x0c13:
  1344.         error(-1, "Got Type 1C InitialRandomSeed");
  1345.         break;
  1346.       case 0x0013:
  1347.         privateDict->subrsOffset = (int)op[0];
  1348.         break;
  1349.       case 0x0014:
  1350.         privateDict->defaultWidthX = op[0];
  1351.         privateDict->defaultWidthXFP = fp[0];
  1352.         break;
  1353.       case 0x0015:
  1354.         privateDict->nominalWidthX = op[0];
  1355.         privateDict->nominalWidthXFP = fp[0];
  1356.         break;
  1357.       default:
  1358.         error(-1, "Unknown Type 1C private dict entry %04x", key);
  1359.         break;
  1360.       }
  1361.       i = 0;
  1362.     } else {
  1363.       x = getNum(&ptr, &isFP);
  1364.       if (i < 48) {
  1365.         op[i] = x;
  1366.         fp[i++] = isFP;
  1367.       }
  1368.     }
  1369.   }
  1370. }
  1371.  
  1372. Gushort *Type1CFontFile::readCharset(int charset, int nGlyphs) {
  1373.   Gushort *glyphNames;
  1374.   Guchar *ptr;
  1375.   int charsetFormat, c;
  1376.   int nLeft, i, j;
  1377.  
  1378.   if (charset == 0) {
  1379.     glyphNames = type1CISOAdobeCharset;
  1380.   } else if (charset == 1) {
  1381.     glyphNames = type1CExpertCharset;
  1382.   } else if (charset == 2) {
  1383.     glyphNames = type1CExpertSubsetCharset;
  1384.   } else {
  1385.     glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
  1386.     glyphNames[0] = 0;
  1387.     ptr = (Guchar *)file + charset;
  1388.     charsetFormat = *ptr++;
  1389.     if (charsetFormat == 0) {
  1390.       for (i = 1; i < nGlyphs; ++i) {
  1391.         glyphNames[i] = getWord(ptr, 2);
  1392.         ptr += 2;
  1393.       }
  1394.     } else if (charsetFormat == 1) {
  1395.       i = 1;
  1396.       while (i < nGlyphs) {
  1397.         c = getWord(ptr, 2);
  1398.         ptr += 2;
  1399.         nLeft = *ptr++;
  1400.         for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
  1401.           glyphNames[i++] = c++;
  1402.         }
  1403.       }
  1404.     } else if (charsetFormat == 2) {
  1405.       i = 1;
  1406.       while (i < nGlyphs) {
  1407.         c = getWord(ptr, 2);
  1408.         ptr += 2;
  1409.         nLeft = getWord(ptr, 2);
  1410.         ptr += 2;
  1411.         for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
  1412.           glyphNames[i++] = c++;
  1413.         }
  1414.       }
  1415.     }
  1416.   }
  1417.   return glyphNames;
  1418. }
  1419.  
  1420. void Type1CFontFile::eexecWrite(char *s) {
  1421.   Guchar *p;
  1422.   Guchar x;
  1423.  
  1424.   for (p = (Guchar *)s; *p; ++p) {
  1425.     x = *p ^ (r1 >> 8);
  1426.     r1 = (x + r1) * 52845 + 22719;
  1427.     (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
  1428.     (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
  1429.     line += 2;
  1430.     if (line == 64) {
  1431.       (*outputFunc)(outputStream, "\n", 1);
  1432.       line = 0;
  1433.     }
  1434.   }
  1435. }
  1436.  
  1437. void Type1CFontFile::eexecCvtGlyph(char *glyphName, Guchar *s, int n) {
  1438.   char eBuf[256];
  1439.  
  1440.   cvtGlyph(s, n);
  1441.   sprintf(eBuf, "/%s %d RD ", glyphName, charBuf->getLength());
  1442.   eexecWrite(eBuf);
  1443.   eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
  1444.   eexecWrite(" ND\n");
  1445.   delete charBuf;
  1446. }
  1447.  
  1448. void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
  1449.   int nHints;
  1450.   int x;
  1451.   GBool first = gTrue;
  1452.   double d, dx, dy;
  1453.   GBool dFP;
  1454.   Gushort r2;
  1455.   Guchar byte;
  1456.   int i, k;
  1457.  
  1458.   charBuf = new GString();
  1459.   charBuf->append((char)73);
  1460.   charBuf->append((char)58);
  1461.   charBuf->append((char)147);
  1462.   charBuf->append((char)134);
  1463.  
  1464.   i = 0;
  1465.   nOps = 0;
  1466.   nHints = 0;
  1467.   while (i < n) {
  1468.     if (s[i] == 12) {
  1469.       switch (s[i+1]) {
  1470.       case 0:                   // dotsection (should be Type 1 only?)
  1471.         // ignored
  1472.         break;
  1473.       case 34:                  // hflex
  1474.         if (nOps != 7) {
  1475.           error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
  1476.         }
  1477.         eexecDumpNum(op[0], fp[0]);
  1478.         eexecDumpNum(0, gFalse);
  1479.         eexecDumpNum(op[1], fp[1]);
  1480.         eexecDumpNum(op[2], fp[2]);
  1481.         eexecDumpNum(op[3], fp[3]);
  1482.         eexecDumpNum(0, gFalse);
  1483.         eexecDumpOp1(8);
  1484.         eexecDumpNum(op[4], fp[4]);
  1485.         eexecDumpNum(0, gFalse);
  1486.         eexecDumpNum(op[5], fp[5]);
  1487.         eexecDumpNum(-op[2], fp[2]);
  1488.         eexecDumpNum(op[6], fp[6]);
  1489.         eexecDumpNum(0, gFalse);
  1490.         eexecDumpOp1(8);
  1491.         break;
  1492.       case 35:                  // flex
  1493.         if (nOps != 13) {
  1494.           error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
  1495.         }
  1496.         eexecDumpNum(op[0], fp[0]);
  1497.         eexecDumpNum(op[1], fp[1]);
  1498.         eexecDumpNum(op[2], fp[2]);
  1499.         eexecDumpNum(op[3], fp[3]);
  1500.         eexecDumpNum(op[4], fp[4]);
  1501.         eexecDumpNum(op[5], fp[5]);
  1502.         eexecDumpOp1(8);
  1503.         eexecDumpNum(op[6], fp[6]);
  1504.         eexecDumpNum(op[7], fp[7]);
  1505.         eexecDumpNum(op[8], fp[8]);
  1506.         eexecDumpNum(op[9], fp[9]);
  1507.         eexecDumpNum(op[10], fp[10]);
  1508.         eexecDumpNum(op[11], fp[11]);
  1509.         eexecDumpOp1(8);
  1510.         break;
  1511.       case 36:                  // hflex1
  1512.         if (nOps != 9) {
  1513.           error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
  1514.         }
  1515.         eexecDumpNum(op[0], fp[0]);
  1516.         eexecDumpNum(op[1], fp[1]);
  1517.         eexecDumpNum(op[2], fp[2]);
  1518.         eexecDumpNum(op[3], fp[3]);
  1519.         eexecDumpNum(op[4], fp[4]);
  1520.         eexecDumpNum(0, gFalse);
  1521.         eexecDumpOp1(8);
  1522.         eexecDumpNum(op[5], fp[5]);
  1523.         eexecDumpNum(0, gFalse);
  1524.         eexecDumpNum(op[6], fp[6]);
  1525.         eexecDumpNum(op[7], fp[7]);
  1526.         eexecDumpNum(op[8], fp[8]);
  1527.         eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]);
  1528.         eexecDumpOp1(8);
  1529.         break;
  1530.       case 37:                  // flex1
  1531.         if (nOps != 11) {
  1532.           error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
  1533.         }
  1534.         eexecDumpNum(op[0], fp[0]);
  1535.         eexecDumpNum(op[1], fp[1]);
  1536.         eexecDumpNum(op[2], fp[2]);
  1537.         eexecDumpNum(op[3], fp[3]);
  1538.         eexecDumpNum(op[4], fp[4]);
  1539.         eexecDumpNum(op[5], fp[5]);
  1540.         eexecDumpOp1(8);
  1541.         eexecDumpNum(op[6], fp[6]);
  1542.         eexecDumpNum(op[7], fp[7]);
  1543.         eexecDumpNum(op[8], fp[8]);
  1544.         eexecDumpNum(op[9], fp[9]);
  1545.         dx = op[0] + op[2] + op[4] + op[6] + op[8];
  1546.         dy = op[1] + op[3] + op[5] + op[7] + op[9];
  1547.         if (fabs(dx) > fabs(dy)) {
  1548.           eexecDumpNum(op[10], fp[10]);
  1549.           eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]);
  1550.         } else {
  1551.           eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]);
  1552.           eexecDumpNum(op[10], fp[10]);
  1553.         }
  1554.         eexecDumpOp1(8);
  1555.         break;
  1556.       case 3:                   // and
  1557.       case 4:                   // or
  1558.       case 5:                   // not
  1559.       case 8:                   // store
  1560.       case 9:                   // abs
  1561.       case 10:                  // add
  1562.       case 11:                  // sub
  1563.       case 12:                  // div
  1564.       case 13:                  // load
  1565.       case 14:                  // neg
  1566.       case 15:                  // eq
  1567.       case 18:                  // drop
  1568.       case 20:                  // put
  1569.       case 21:                  // get
  1570.       case 22:                  // ifelse
  1571.       case 23:                  // random
  1572.       case 24:                  // mul
  1573.       case 26:                  // sqrt
  1574.       case 27:                  // dup
  1575.       case 28:                  // exch
  1576.       case 29:                  // index
  1577.       case 30:                  // roll
  1578.         error(-1, "Unimplemented Type 2 charstring op: 12.%d", s[i+1]);
  1579.         break;
  1580.       default:
  1581.         error(-1, "Illegal Type 2 charstring op: 12.%d", s[i+1]);
  1582.         break;
  1583.       }
  1584.       i += 2;
  1585.       nOps = 0;
  1586.     } else if (s[i] == 19) {    // hintmask
  1587.       // ignored
  1588.       if (first) {
  1589.         cvtGlyphWidth(nOps == 1);
  1590.         first = gFalse;
  1591.       }
  1592.       if (nOps > 0) {
  1593.         if (nOps & 1) {
  1594.           error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
  1595.                 nOps);
  1596.         }
  1597.         nHints += nOps / 2;
  1598.       }
  1599.       i += 1 + ((nHints + 7) >> 3);
  1600.       nOps = 0;
  1601.     } else if (s[i] == 20) {    // cntrmask
  1602.       // ignored
  1603.       if (first) {
  1604.         cvtGlyphWidth(nOps == 1);
  1605.         first = gFalse;
  1606.       }
  1607.       if (nOps > 0) {
  1608.         if (nOps & 1) {
  1609.           error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
  1610.                 nOps);
  1611.         }
  1612.         nHints += nOps / 2;
  1613.       }
  1614.       i += 1 + ((nHints + 7) >> 3);
  1615.       nOps = 0;
  1616.     } else if (s[i] == 28) {
  1617.       x = (s[i+1] << 8) + s[i+2];
  1618.       if (x & 0x8000) {
  1619.         x |= -1 << 15;
  1620.       }
  1621.       if (nOps < 48) {
  1622.         fp[nOps] = gFalse;
  1623.         op[nOps++] = x;
  1624.       }
  1625.       i += 3;
  1626.     } else if (s[i] <= 31) {
  1627.       switch (s[i]) {
  1628.       case 4:                   // vmoveto
  1629.         if (first) {
  1630.           cvtGlyphWidth(nOps == 2);
  1631.           first = gFalse;
  1632.         }
  1633.         if (nOps != 1) {
  1634.           error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
  1635.         }
  1636.         eexecDumpNum(op[0], fp[0]);
  1637.         eexecDumpOp1(4);
  1638.         break;
  1639.       case 5:                   // rlineto
  1640.         if (nOps < 2 || nOps % 2 != 0) {
  1641.           error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
  1642.         }
  1643.         for (k = 0; k < nOps; k += 2) {
  1644.           eexecDumpNum(op[k], fp[k]);
  1645.           eexecDumpNum(op[k+1], fp[k+1]);
  1646.           eexecDumpOp1(5);
  1647.         }
  1648.         break;
  1649.       case 6:                   // hlineto
  1650.         if (nOps < 1) {
  1651.           error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
  1652.         }
  1653.         for (k = 0; k < nOps; ++k) {
  1654.           eexecDumpNum(op[k], fp[k]);
  1655.           eexecDumpOp1((k & 1) ? 7 : 6);
  1656.         }
  1657.         break;
  1658.       case 7:                   // vlineto
  1659.         if (nOps < 1) {
  1660.           error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
  1661.         }
  1662.         for (k = 0; k < nOps; ++k) {
  1663.           eexecDumpNum(op[k], fp[k]);
  1664.           eexecDumpOp1((k & 1) ? 6 : 7);
  1665.         }
  1666.         break;
  1667.       case 8:                   // rrcurveto
  1668.         if (nOps < 6 || nOps % 6 != 0) {
  1669.           error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
  1670.         }
  1671.         for (k = 0; k < nOps; k += 6) {
  1672.           eexecDumpNum(op[k], fp[k]);
  1673.           eexecDumpNum(op[k+1], fp[k+1]);
  1674.           eexecDumpNum(op[k+2], fp[k+2]);
  1675.           eexecDumpNum(op[k+3], fp[k+3]);
  1676.           eexecDumpNum(op[k+4], fp[k+4]);
  1677.           eexecDumpNum(op[k+5], fp[k+5]);
  1678.           eexecDumpOp1(8);
  1679.         }
  1680.         break;
  1681.       case 14:                  // endchar / seac
  1682.         if (first) {
  1683.           cvtGlyphWidth(nOps == 1 || nOps == 5);
  1684.           first = gFalse;
  1685.         }
  1686.         if (nOps == 4) {
  1687.           eexecDumpNum(0, 0);
  1688.           eexecDumpNum(op[0], fp[0]);
  1689.           eexecDumpNum(op[1], fp[1]);
  1690.           eexecDumpNum(op[2], fp[2]);
  1691.           eexecDumpNum(op[3], fp[3]);
  1692.           eexecDumpOp2(6);
  1693.         } else if (nOps == 0) {
  1694.           eexecDumpOp1(14);
  1695.         } else {
  1696.           error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
  1697.         }
  1698.         break;
  1699.       case 21:                  // rmoveto
  1700.         if (first) {
  1701.           cvtGlyphWidth(nOps == 3);
  1702.           first = gFalse;
  1703.         }
  1704.         if (nOps != 2) {
  1705.           error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
  1706.         }
  1707.         eexecDumpNum(op[0], fp[0]);
  1708.         eexecDumpNum(op[1], fp[1]);
  1709.         eexecDumpOp1(21);
  1710.         break;
  1711.       case 22:                  // hmoveto
  1712.         if (first) {
  1713.           cvtGlyphWidth(nOps == 2);
  1714.           first = gFalse;
  1715.         }
  1716.         if (nOps != 1) {
  1717.           error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
  1718.         }
  1719.         eexecDumpNum(op[0], fp[0]);
  1720.         eexecDumpOp1(22);
  1721.         break;
  1722.       case 24:                  // rcurveline
  1723.         if (nOps < 8 || (nOps - 2) % 6 != 0) {
  1724.           error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
  1725.         }
  1726.         for (k = 0; k < nOps - 2; k += 6) {
  1727.           eexecDumpNum(op[k], fp[k]);
  1728.           eexecDumpNum(op[k+1], fp[k+1]);
  1729.           eexecDumpNum(op[k+2], fp[k+2]);
  1730.           eexecDumpNum(op[k+3], fp[k+3]);
  1731.           eexecDumpNum(op[k+4], fp[k+4]);
  1732.           eexecDumpNum(op[k+5], fp[k+5]);
  1733.           eexecDumpOp1(8);
  1734.         }
  1735.         eexecDumpNum(op[k], fp[k]);
  1736.         eexecDumpNum(op[k+1], fp[k]);
  1737.         eexecDumpOp1(5);
  1738.         break;
  1739.       case 25:                  // rlinecurve
  1740.         if (nOps < 8 || (nOps - 6) % 2 != 0) {
  1741.           error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
  1742.         }
  1743.         for (k = 0; k < nOps - 6; k += 2) {
  1744.           eexecDumpNum(op[k], fp[k]);
  1745.           eexecDumpNum(op[k+1], fp[k]);
  1746.           eexecDumpOp1(5);
  1747.         }
  1748.         eexecDumpNum(op[k], fp[k]);
  1749.         eexecDumpNum(op[k+1], fp[k+1]);
  1750.         eexecDumpNum(op[k+2], fp[k+2]);
  1751.         eexecDumpNum(op[k+3], fp[k+3]);
  1752.         eexecDumpNum(op[k+4], fp[k+4]);
  1753.         eexecDumpNum(op[k+5], fp[k+5]);
  1754.         eexecDumpOp1(8);
  1755.         break;
  1756.       case 26:                  // vvcurveto
  1757.         if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
  1758.           error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
  1759.         }
  1760.         if (nOps % 2 == 1) {
  1761.           eexecDumpNum(op[0], fp[0]);
  1762.           eexecDumpNum(op[1], fp[1]);
  1763.           eexecDumpNum(op[2], fp[2]);
  1764.           eexecDumpNum(op[3], fp[3]);
  1765.           eexecDumpNum(0, gFalse);
  1766.           eexecDumpNum(op[4], fp[4]);
  1767.           eexecDumpOp1(8);
  1768.           k = 5;
  1769.         } else {
  1770.           k = 0;
  1771.         }
  1772.         for (; k < nOps; k += 4) {
  1773.           eexecDumpNum(0, gFalse);
  1774.           eexecDumpNum(op[k], fp[k]);
  1775.           eexecDumpNum(op[k+1], fp[k+1]);
  1776.           eexecDumpNum(op[k+2], fp[k+2]);
  1777.           eexecDumpNum(0, gFalse);
  1778.           eexecDumpNum(op[k+3], fp[k+3]);
  1779.           eexecDumpOp1(8);
  1780.         }
  1781.         break;
  1782.       case 27:                  // hhcurveto
  1783.         if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
  1784.           error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
  1785.         }
  1786.         if (nOps % 2 == 1) {
  1787.           eexecDumpNum(op[1], fp[1]);
  1788.           eexecDumpNum(op[0], fp[0]);
  1789.           eexecDumpNum(op[2], fp[2]);
  1790.           eexecDumpNum(op[3], fp[3]);
  1791.           eexecDumpNum(op[4], fp[4]);
  1792.           eexecDumpNum(0, gFalse);
  1793.           eexecDumpOp1(8);
  1794.           k = 5;
  1795.         } else {
  1796.           k = 0;
  1797.         }
  1798.         for (; k < nOps; k += 4) {
  1799.           eexecDumpNum(op[k], fp[k]);
  1800.           eexecDumpNum(0, gFalse);
  1801.           eexecDumpNum(op[k+1], fp[k+1]);
  1802.           eexecDumpNum(op[k+2], fp[k+2]);
  1803.           eexecDumpNum(op[k+3], fp[k+3]);
  1804.           eexecDumpNum(0, gFalse);
  1805.           eexecDumpOp1(8);
  1806.         }
  1807.         break;
  1808.       case 30:                  // vhcurveto
  1809.         if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
  1810.           error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
  1811.         }
  1812.         for (k = 0; k < nOps && k != nOps-5; k += 4) {
  1813.           if (k % 8 == 0) {
  1814.             eexecDumpNum(op[k], fp[k]);
  1815.             eexecDumpNum(op[k+1], fp[k+1]);
  1816.             eexecDumpNum(op[k+2], fp[k+2]);
  1817.             eexecDumpNum(op[k+3], fp[k+3]);
  1818.             eexecDumpOp1(30);
  1819.           } else {
  1820.             eexecDumpNum(op[k], fp[k]);
  1821.             eexecDumpNum(op[k+1], fp[k+1]);
  1822.             eexecDumpNum(op[k+2], fp[k+2]);
  1823.             eexecDumpNum(op[k+3], fp[k+3]);
  1824.             eexecDumpOp1(31);
  1825.           }
  1826.         }
  1827.         if (k == nOps-5) {
  1828.           if (k % 8 == 0) {
  1829.             eexecDumpNum(0, gFalse);
  1830.             eexecDumpNum(op[k], fp[k]);
  1831.             eexecDumpNum(op[k+1], fp[k+1]);
  1832.             eexecDumpNum(op[k+2], fp[k+2]);
  1833.             eexecDumpNum(op[k+3], fp[k+3]);
  1834.             eexecDumpNum(op[k+4], fp[k+4]);
  1835.           } else {
  1836.             eexecDumpNum(op[k], fp[k]);
  1837.             eexecDumpNum(0, gFalse);
  1838.             eexecDumpNum(op[k+1], fp[k+1]);
  1839.             eexecDumpNum(op[k+2], fp[k+2]);
  1840.             eexecDumpNum(op[k+4], fp[k+4]);
  1841.             eexecDumpNum(op[k+3], fp[k+3]);
  1842.           }
  1843.           eexecDumpOp1(8);
  1844.         }
  1845.         break;
  1846.       case 31:                  // hvcurveto
  1847.         if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
  1848.           error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
  1849.         }
  1850.         for (k = 0; k < nOps && k != nOps-5; k += 4) {
  1851.           if (k % 8 == 0) {
  1852.             eexecDumpNum(op[k], fp[k]);
  1853.             eexecDumpNum(op[k+1], fp[k+1]);
  1854.             eexecDumpNum(op[k+2], fp[k+2]);
  1855.             eexecDumpNum(op[k+3], fp[k+3]);
  1856.             eexecDumpOp1(31);
  1857.           } else {
  1858.             eexecDumpNum(op[k], fp[k]);
  1859.             eexecDumpNum(op[k+1], fp[k+1]);
  1860.             eexecDumpNum(op[k+2], fp[k+2]);
  1861.             eexecDumpNum(op[k+3], fp[k+3]);
  1862.             eexecDumpOp1(30);
  1863.           }
  1864.         }
  1865.         if (k == nOps-5) {
  1866.           if (k % 8 == 0) {
  1867.             eexecDumpNum(op[k], fp[k]);
  1868.             eexecDumpNum(0, gFalse);
  1869.             eexecDumpNum(op[k+1], fp[k+1]);
  1870.             eexecDumpNum(op[k+2], fp[k+2]);
  1871.             eexecDumpNum(op[k+4], fp[k+4]);
  1872.             eexecDumpNum(op[k+3], fp[k+3]);
  1873.           } else {
  1874.             eexecDumpNum(0, gFalse);
  1875.             eexecDumpNum(op[k], fp[k]);
  1876.             eexecDumpNum(op[k+1], fp[k+1]);
  1877.             eexecDumpNum(op[k+2], fp[k+2]);
  1878.             eexecDumpNum(op[k+3], fp[k+3]);
  1879.             eexecDumpNum(op[k+4], fp[k+4]);
  1880.           }
  1881.           eexecDumpOp1(8);
  1882.         }
  1883.         break;
  1884.       case 1:                   // hstem
  1885.         if (first) {
  1886.           cvtGlyphWidth(nOps & 1);
  1887.           first = gFalse;
  1888.         }
  1889.         if (nOps & 1) {
  1890.           error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
  1891.         }
  1892.         d = 0;
  1893.         dFP = gFalse;
  1894.         for (k = 0; k < nOps; k += 2) {
  1895.           if (op[k+1] < 0) {
  1896.             d += op[k] + op[k+1];
  1897.             dFP |= fp[k] | fp[k+1];
  1898.             eexecDumpNum(d, dFP);
  1899.             eexecDumpNum(-op[k+1], fp[k+1]);
  1900.           } else {
  1901.             d += op[k];
  1902.             dFP |= fp[k];
  1903.             eexecDumpNum(d, dFP);
  1904.             eexecDumpNum(op[k+1], fp[k+1]);
  1905.             d += op[k+1];
  1906.             dFP |= fp[k+1];
  1907.           }
  1908.           eexecDumpOp1(1);
  1909.         }
  1910.         nHints += nOps / 2;
  1911.         break;
  1912.       case 3:                   // vstem
  1913.         if (first) {
  1914.           cvtGlyphWidth(nOps & 1);
  1915.           first = gFalse;
  1916.         }
  1917.         if (nOps & 1) {
  1918.           error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
  1919.         }
  1920.         d = 0;
  1921.         dFP = gFalse;
  1922.         for (k = 0; k < nOps; k += 2) {
  1923.           if (op[k+1] < 0) {
  1924.             d += op[k] + op[k+1];
  1925.             dFP |= fp[k] | fp[k+1];
  1926.             eexecDumpNum(d, dFP);
  1927.             eexecDumpNum(-op[k+1], fp[k+1]);
  1928.           } else {
  1929.             d += op[k];
  1930.             dFP |= fp[k];
  1931.             eexecDumpNum(d, dFP);
  1932.             eexecDumpNum(op[k+1], fp[k+1]);
  1933.             d += op[k+1];
  1934.             dFP |= fp[k+1];
  1935.           }
  1936.           eexecDumpOp1(3);
  1937.         }
  1938.         nHints += nOps / 2;
  1939.         break;
  1940.       case 18:                  // hstemhm
  1941.         // ignored
  1942.         if (first) {
  1943.           cvtGlyphWidth(nOps & 1);
  1944.           first = gFalse;
  1945.         }
  1946.         if (nOps & 1) {
  1947.           error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
  1948.         }
  1949.         nHints += nOps / 2;
  1950.         break;
  1951.       case 23:                  // vstemhm
  1952.         // ignored
  1953.         if (first) {
  1954.           cvtGlyphWidth(nOps & 1);
  1955.           first = gFalse;
  1956.         }
  1957.         if (nOps & 1) {
  1958.           error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
  1959.         }
  1960.         nHints += nOps / 2;
  1961.         break;
  1962.       case 10:                  // callsubr
  1963.       case 11:                  // return
  1964.       case 16:                  // blend
  1965.       case 29:                  // callgsubr
  1966.         error(-1, "Unimplemented Type 2 charstring op: %d", s[i]);
  1967.         break;
  1968.       default:
  1969.         error(-1, "Illegal Type 2 charstring op: %d", s[i]);
  1970.         break;
  1971.       }
  1972.       ++i;
  1973.       nOps = 0;
  1974.     } else if (s[i] <= 246) {
  1975.       if (nOps < 48) {
  1976.         fp[nOps] = gFalse;
  1977.         op[nOps++] = (int)s[i] - 139;
  1978.       }
  1979.       ++i;
  1980.     } else if (s[i] <= 250) {
  1981.       if (nOps < 48) {
  1982.         fp[nOps] = gFalse;
  1983.         op[nOps++] = (((int)s[i] - 247) << 8) + (int)s[i+1] + 108;
  1984.       }
  1985.       i += 2;
  1986.     } else if (s[i] <= 254) {
  1987.       if (nOps < 48) {
  1988.         fp[nOps] = gFalse;
  1989.         op[nOps++] = -(((int)s[i] - 251) << 8) - (int)s[i+1] - 108;
  1990.       }
  1991.       i += 2;
  1992.     } else {
  1993.       x = (s[i+1] << 24) | (s[i+2] << 16) | (s[i+3] << 8) | s[i+4];
  1994.       if (x & 0x80000000)
  1995.         x |= -1 << 31;
  1996.       if (nOps < 48) {
  1997.         fp[nOps] = gTrue;
  1998.         op[nOps++] = (double)x / 65536.0;
  1999.       }
  2000.       i += 5;
  2001.     }
  2002.   }
  2003.  
  2004.   // charstring encryption
  2005.   r2 = 4330;
  2006.   for (i = 0; i < charBuf->getLength(); ++i) {
  2007.     byte = charBuf->getChar(i) ^ (r2 >> 8);
  2008.     charBuf->setChar(i, byte);
  2009.     r2 = (byte + r2) * 52845 + 22719;
  2010.   }
  2011. }
  2012.  
  2013. void Type1CFontFile::cvtGlyphWidth(GBool useOp) {
  2014.   double w;
  2015.   GBool wFP;
  2016.   int i;
  2017.  
  2018.   if (useOp) {
  2019.     w = nominalWidthX + op[0];
  2020.     wFP = nominalWidthXFP | fp[0];
  2021.     for (i = 1; i < nOps; ++i) {
  2022.       op[i-1] = op[i];
  2023.       fp[i-1] = fp[i];
  2024.     }
  2025.     --nOps;
  2026.   } else {
  2027.     w = defaultWidthX;
  2028.     wFP = defaultWidthXFP;
  2029.   }
  2030.   eexecDumpNum(0, gFalse);
  2031.   eexecDumpNum(w, wFP);
  2032.   eexecDumpOp1(13);
  2033. }
  2034.  
  2035. void Type1CFontFile::eexecDumpNum(double x, GBool fpA) {
  2036.   Guchar buf[12];
  2037.   int y, n;
  2038.  
  2039.   n = 0;
  2040.   if (fpA) {
  2041.     if (x >= -32768 && x < 32768) {
  2042.       y = (int)(x * 256.0);
  2043.       buf[0] = 255;
  2044.       buf[1] = (Guchar)(y >> 24);
  2045.       buf[2] = (Guchar)(y >> 16);
  2046.       buf[3] = (Guchar)(y >> 8);
  2047.       buf[4] = (Guchar)y;
  2048.       buf[5] = 255;
  2049.       buf[6] = 0;
  2050.       buf[7] = 0;
  2051.       buf[8] = 1;
  2052.       buf[9] = 0;
  2053.       buf[10] = 12;
  2054.       buf[11] = 12;
  2055.       n = 12;
  2056.     } else {
  2057.       error(-1, "Type 2 fixed point constant out of range");
  2058.     }
  2059.   } else {
  2060.     y = (int)x;
  2061.     if (y >= -107 && y <= 107) {
  2062.       buf[0] = (Guchar)(y + 139);
  2063.       n = 1;
  2064.     } else if (y > 107 && y <= 1131) {
  2065.       y -= 108;
  2066.       buf[0] = (Guchar)((y >> 8) + 247);
  2067.       buf[1] = (Guchar)(y & 0xff);
  2068.       n = 2;
  2069.     } else if (y < -107 && y >= -1131) {
  2070.       y = -y - 108;
  2071.       buf[0] = (Guchar)((y >> 8) + 251);
  2072.       buf[1] = (Guchar)(y & 0xff);
  2073.       n = 2;
  2074.     } else {
  2075.       buf[0] = 255;
  2076.       buf[1] = (Guchar)(y >> 24);
  2077.       buf[2] = (Guchar)(y >> 16);
  2078.       buf[3] = (Guchar)(y >> 8);
  2079.       buf[4] = (Guchar)y;
  2080.       n = 5;
  2081.     }
  2082.   }
  2083.   charBuf->append((char *)buf, n);
  2084. }
  2085.  
  2086. void Type1CFontFile::eexecDumpOp1(int opA) {
  2087.   charBuf->append((char)opA);
  2088. }
  2089.  
  2090. void Type1CFontFile::eexecDumpOp2(int opA) {
  2091.   charBuf->append((char)12);
  2092.   charBuf->append((char)opA);
  2093. }
  2094.  
  2095. void Type1CFontFile::eexecWriteCharstring(Guchar *s, int n) {
  2096.   Guchar x;
  2097.   int i;
  2098.  
  2099.   // eexec encryption
  2100.   for (i = 0; i < n; ++i) {
  2101.     x = s[i] ^ (r1 >> 8);
  2102.     r1 = (x + r1) * 52845 + 22719;
  2103.     (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
  2104.     (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
  2105.     line += 2;
  2106.     if (line == 64) {
  2107.       (*outputFunc)(outputStream, "\n", 1);
  2108.       line = 0;
  2109.     }
  2110.   }
  2111. }
  2112.  
  2113. void Type1CFontFile::getDeltaInt(char *buf, char *key, double *opA,
  2114.                                  int n) {
  2115. //**** Colin Granville ****
  2116. #ifdef ACORN
  2117.   unsigned int x, i;
  2118. #else
  2119.   int x, i;
  2120. #endif
  2121. //**** end Colin Granville ****
  2122.  
  2123.   sprintf(buf, "/%s [", key);
  2124.   buf += strlen(buf);
  2125.   x = 0;
  2126.   for (i = 0; i < n; ++i) {
  2127. //**** Colin Granville ****
  2128. #ifdef ACORN
  2129.     x += (unsigned int)opA[i];
  2130. #else
  2131.     x += (int)opA[i];
  2132. #endif
  2133. //**** end Colin Granville ****
  2134.  
  2135.     sprintf(buf, "%s%d", i > 0 ? " " : "", x);
  2136.     buf += strlen(buf);
  2137.   }
  2138.   sprintf(buf, "] def\n");
  2139. }
  2140.  
  2141. void Type1CFontFile::getDeltaReal(char *buf, char *key, double *opA,
  2142.                                   int n) {
  2143.   double x;
  2144.   int i;
  2145.  
  2146.   sprintf(buf, "/%s [", key);
  2147.   buf += strlen(buf);
  2148.   x = 0;
  2149.   for (i = 0; i < n; ++i) {
  2150.     x += opA[i];
  2151.     sprintf(buf, "%s%g", i > 0 ? " " : "", x);
  2152.     buf += strlen(buf);
  2153.   }
  2154.   sprintf(buf, "] def\n");
  2155. }
  2156.  
  2157. int Type1CFontFile::getIndexLen(Guchar *indexPtr) {
  2158.   return (int)getWord(indexPtr, 2);
  2159. }
  2160.  
  2161. Guchar *Type1CFontFile::getIndexValPtr(Guchar *indexPtr, int i) {
  2162.   int n, offSize;
  2163.   Guchar *idxStartPtr;
  2164.  
  2165.   n = (int)getWord(indexPtr, 2);
  2166.   offSize = indexPtr[2];
  2167.   idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
  2168.   return idxStartPtr + getWord(indexPtr + 3 + i * offSize, offSize);
  2169. }
  2170.  
  2171. Guchar *Type1CFontFile::getIndexEnd(Guchar *indexPtr) {
  2172.   int n, offSize;
  2173.   Guchar *idxStartPtr;
  2174.  
  2175.   n = (int)getWord(indexPtr, 2);
  2176.   offSize = indexPtr[2];
  2177.   idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
  2178.   return idxStartPtr + getWord(indexPtr + 3 + n * offSize, offSize);
  2179. }
  2180.  
  2181. Guint Type1CFontFile::getWord(Guchar *ptr, int size) {
  2182.   Guint x;
  2183.   int i;
  2184.  
  2185.   x = 0;
  2186.   for (i = 0; i < size; ++i) {
  2187.     x = (x << 8) + *ptr++;
  2188.   }
  2189.   return x;
  2190. }
  2191.  
  2192. double Type1CFontFile::getNum(Guchar **ptr, GBool *isFP) {
  2193.   static char nybChars[16] = "0123456789.ee -";
  2194.   int b0, b, nyb0, nyb1;
  2195.   double x;
  2196.   char buf[65];
  2197.   int i;
  2198.  
  2199.   x = 0;
  2200.   *isFP = gFalse;
  2201.   b0 = (*ptr)[0];
  2202.   if (b0 < 28) {
  2203.     x = 0;
  2204.   } else if (b0 == 28) {
  2205.     x = ((*ptr)[1] << 8) + (*ptr)[2];
  2206.     *ptr += 3;
  2207.   } else if (b0 == 29) {
  2208.     x = ((*ptr)[1] << 24) + ((*ptr)[2] << 16) + ((*ptr)[3] << 8) + (*ptr)[4];
  2209.     *ptr += 5;
  2210.   } else if (b0 == 30) {
  2211.     *ptr += 1;
  2212.     i = 0;
  2213.     do {
  2214.       b = *(*ptr)++;
  2215.       nyb0 = b >> 4;
  2216.       nyb1 = b & 0x0f;
  2217.       if (nyb0 == 0xf) {
  2218.         break;
  2219.       }
  2220.       buf[i++] = nybChars[nyb0];
  2221.       if (i == 64) {
  2222.         break;
  2223.       }
  2224.       if (nyb0 == 0xc) {
  2225.         buf[i++] = '-';
  2226.       }
  2227.       if (i == 64) {
  2228.         break;
  2229.       }
  2230.       if (nyb1 == 0xf) {
  2231.         break;
  2232.       }
  2233.       buf[i++] = nybChars[nyb1];
  2234.       if (i == 64) {
  2235.         break;
  2236.       }
  2237.       if (nyb1 == 0xc) {
  2238.         buf[i++] = '-';
  2239.       }
  2240.     } while (i < 64);
  2241.     buf[i] = '\0';
  2242.     x = atof(buf);
  2243.     *isFP = gTrue;
  2244.   } else if (b0 == 31) {
  2245.     x = 0;
  2246.   } else if (b0 < 247) {
  2247.     x = b0 - 139;
  2248.     *ptr += 1;
  2249.   } else if (b0 < 251) {
  2250.     x = ((b0 - 247) << 8) + (*ptr)[1] + 108;
  2251.     *ptr += 2;
  2252.   } else {
  2253.     x = -((b0 - 251) << 8) - (*ptr)[1] - 108;
  2254.     *ptr += 2;
  2255.   }
  2256.   return x;
  2257. }
  2258.  
  2259. char *Type1CFontFile::getString(int sid, char *buf) {
  2260.   Guchar *idxPtr0, *idxPtr1;
  2261.   int n;
  2262.  
  2263.   if (sid < 391) {
  2264.     strcpy(buf, type1CStdStrings[sid]);
  2265.   } else {
  2266.     sid -= 391;
  2267.     idxPtr0 = getIndexValPtr(stringIdxPtr, sid);
  2268.     idxPtr1 = getIndexValPtr(stringIdxPtr, sid + 1);
  2269.     if ((n = idxPtr1 - idxPtr0) > 255) {
  2270.       n = 255;
  2271.     }
  2272.     strncpy(buf, (char *)idxPtr0, n);
  2273.     buf[n] = '\0';
  2274.   }
  2275.   return buf;
  2276. }
  2277.  
  2278. //------------------------------------------------------------------------
  2279. // TrueTypeFontFile
  2280. //------------------------------------------------------------------------
  2281.  
  2282. //
  2283. // Terminology
  2284. // -----------
  2285. //
  2286. // character code = number used as an element of a text string
  2287. //
  2288. // character name = glyph name = name for a particular glyph within a
  2289. //                  font
  2290. //
  2291. // glyph index = position (within some internal table in the font)
  2292. //               where the instructions to draw a particular glyph are
  2293. //               stored
  2294. //
  2295. // Type 1 fonts
  2296. // ------------
  2297. //
  2298. // Type 1 fonts contain:
  2299. //
  2300. // Encoding: array of glyph names, maps char codes to glyph names
  2301. //
  2302. //           Encoding[charCode] = charName
  2303. //
  2304. // CharStrings: dictionary of instructions, keyed by character names,
  2305. //              maps character name to glyph data
  2306. //
  2307. //              CharStrings[charName] = glyphData
  2308. //
  2309. // TrueType fonts
  2310. // --------------
  2311. //
  2312. // TrueType fonts contain:
  2313. //
  2314. // 'cmap' table: mapping from character code to glyph index; there may
  2315. //               be multiple cmaps in a TrueType font
  2316. //
  2317. //               cmap[charCode] = glyphIdx
  2318. //
  2319. // 'post' table: mapping from glyph index to glyph name
  2320. //
  2321. //               post[glyphIdx] = glyphName
  2322. //
  2323. // Type 42 fonts
  2324. // -------------
  2325. //
  2326. // Type 42 fonts contain:
  2327. //
  2328. // Encoding: array of glyph names, maps char codes to glyph names
  2329. //
  2330. //           Encoding[charCode] = charName
  2331. //
  2332. // CharStrings: dictionary of glyph indexes, keyed by character names,
  2333. //              maps character name to glyph index
  2334. //
  2335. //              CharStrings[charName] = glyphIdx
  2336. //
  2337.  
  2338. struct TTFontTableHdr {
  2339.   char tag[4];
  2340.   Guint checksum;
  2341.   Guint offset;
  2342.   Guint length;
  2343. };
  2344.  
  2345. struct T42Table {
  2346.   char *tag;                    // 4-byte tag
  2347.   GBool required;               // required by the TrueType spec?
  2348. };
  2349.  
  2350. // TrueType tables to be embedded in Type 42 fonts.
  2351. // NB: the table names must be in alphabetical order here.
  2352. #define nT42Tables 11
  2353. static T42Table t42Tables[nT42Tables] = {
  2354.   { "cvt ", gTrue  },
  2355.   { "fpgm", gTrue  },
  2356.   { "glyf", gTrue  },
  2357.   { "head", gTrue  },
  2358.   { "hhea", gTrue  },
  2359.   { "hmtx", gTrue  },
  2360.   { "loca", gTrue  },
  2361.   { "maxp", gTrue  },
  2362.   { "prep", gTrue  },
  2363.   { "vhea", gFalse },
  2364.   { "vmtx", gFalse }
  2365. };
  2366. #define t42HeadTable 3
  2367. #define t42LocaTable 6
  2368. #define t42GlyfTable 2
  2369.  
  2370. // Glyph names in some arbitrary standard that Apple uses for their
  2371. // TrueType fonts.
  2372. static char *macGlyphNames[258] = {
  2373.   ".notdef",
  2374.   "null",
  2375.   "CR",
  2376.   "space",
  2377.   "exclam",
  2378.   "quotedbl",
  2379.   "numbersign",
  2380.   "dollar",
  2381.   "percent",
  2382.   "ampersand",
  2383.   "quotesingle",
  2384.   "parenleft",
  2385.   "parenright",
  2386.   "asterisk",
  2387.   "plus",
  2388.   "comma",
  2389.   "hyphen",
  2390.   "period",
  2391.   "slash",
  2392.   "zero",
  2393.   "one",
  2394.   "two",
  2395.   "three",
  2396.   "four",
  2397.   "five",
  2398.   "six",
  2399.   "seven",
  2400.   "eight",
  2401.   "nine",
  2402.   "colon",
  2403.   "semicolon",
  2404.   "less",
  2405.   "equal",
  2406.   "greater",
  2407.   "question",
  2408.   "at",
  2409.   "A",
  2410.   "B",
  2411.   "C",
  2412.   "D",
  2413.   "E",
  2414.   "F",
  2415.   "G",
  2416.   "H",
  2417.   "I",
  2418.   "J",
  2419.   "K",
  2420.   "L",
  2421.   "M",
  2422.   "N",
  2423.   "O",
  2424.   "P",
  2425.   "Q",
  2426.   "R",
  2427.   "S",
  2428.   "T",
  2429.   "U",
  2430.   "V",
  2431.   "W",
  2432.   "X",
  2433.   "Y",
  2434.   "Z",
  2435.   "bracketleft",
  2436.   "backslash",
  2437.   "bracketright",
  2438.   "asciicircum",
  2439.   "underscore",
  2440.   "grave",
  2441.   "a",
  2442.   "b",
  2443.   "c",
  2444.   "d",
  2445.   "e",
  2446.   "f",
  2447.   "g",
  2448.   "h",
  2449.   "i",
  2450.   "j",
  2451.   "k",
  2452.   "l",
  2453.   "m",
  2454.   "n",
  2455.   "o",
  2456.   "p",
  2457.   "q",
  2458.   "r",
  2459.   "s",
  2460.   "t",
  2461.   "u",
  2462.   "v",
  2463.   "w",
  2464.   "x",
  2465.   "y",
  2466.   "z",
  2467.   "braceleft",
  2468.   "bar",
  2469.   "braceright",
  2470.   "asciitilde",
  2471.   "Adieresis",
  2472.   "Aring",
  2473.   "Ccedilla",
  2474.   "Eacute",
  2475.   "Ntilde",
  2476.   "Odieresis",
  2477.   "Udieresis",
  2478.   "aacute",
  2479.   "agrave",
  2480.   "acircumflex",
  2481.   "adieresis",
  2482.   "atilde",
  2483.   "aring",
  2484.   "ccedilla",
  2485.   "eacute",
  2486.   "egrave",
  2487.   "ecircumflex",
  2488.   "edieresis",
  2489.   "iacute",
  2490.   "igrave",
  2491.   "icircumflex",
  2492.   "idieresis",
  2493.   "ntilde",
  2494.   "oacute",
  2495.   "ograve",
  2496.   "ocircumflex",
  2497.   "odieresis",
  2498.   "otilde",
  2499.   "uacute",
  2500.   "ugrave",
  2501.   "ucircumflex",
  2502.   "udieresis",
  2503.   "dagger",
  2504.   "degree",
  2505.   "cent",
  2506.   "sterling",
  2507.   "section",
  2508.   "bullet",
  2509.   "paragraph",
  2510.   "germandbls",
  2511.   "registered",
  2512.   "copyright",
  2513.   "trademark",
  2514.   "acute",
  2515.   "dieresis",
  2516.   "notequal",
  2517.   "AE",
  2518.   "Oslash",
  2519.   "infinity",
  2520.   "plusminus",
  2521.   "lessequal",
  2522.   "greaterequal",
  2523.   "yen",
  2524.   "mu1",
  2525.   "partialdiff",
  2526.   "summation",
  2527.   "product",
  2528.   "pi",
  2529.   "integral",
  2530.   "ordfeminine",
  2531.   "ordmasculine",
  2532.   "Ohm",
  2533.   "ae",
  2534.   "oslash",
  2535.   "questiondown",
  2536.   "exclamdown",
  2537.   "logicalnot",
  2538.   "radical",
  2539.   "florin",
  2540.   "approxequal",
  2541.   "increment",
  2542.   "guillemotleft",
  2543.   "guillemotright",
  2544.   "ellipsis",
  2545.   "nbspace",
  2546.   "Agrave",
  2547.   "Atilde",
  2548.   "Otilde",
  2549.   "OE",
  2550.   "oe",
  2551.   "endash",
  2552.   "emdash",
  2553.   "quotedblleft",
  2554.   "quotedblright",
  2555.   "quoteleft",
  2556.   "quoteright",
  2557.   "divide",
  2558.   "lozenge",
  2559.   "ydieresis",
  2560.   "Ydieresis",
  2561.   "fraction",
  2562.   "currency",
  2563.   "guilsinglleft",
  2564.   "guilsinglright",
  2565.   "fi",
  2566.   "fl",
  2567.   "daggerdbl",
  2568.   "periodcentered",
  2569.   "quotesinglbase",
  2570.   "quotedblbase",
  2571.   "perthousand",
  2572.   "Acircumflex",
  2573.   "Ecircumflex",
  2574.   "Aacute",
  2575.   "Edieresis",
  2576.   "Egrave",
  2577.   "Iacute",
  2578.   "Icircumflex",
  2579.   "Idieresis",
  2580.   "Igrave",
  2581.   "Oacute",
  2582.   "Ocircumflex",
  2583.   "applelogo",
  2584.   "Ograve",
  2585.   "Uacute",
  2586.   "Ucircumflex",
  2587.   "Ugrave",
  2588.   "dotlessi",
  2589.   "circumflex",
  2590.   "tilde",
  2591.   "overscore",
  2592.   "breve",
  2593.   "dotaccent",
  2594.   "ring",
  2595.   "cedilla",
  2596.   "hungarumlaut",
  2597.   "ogonek",
  2598.   "caron",
  2599.   "Lslash",
  2600.   "lslash",
  2601.   "Scaron",
  2602.   "scaron",
  2603.   "Zcaron",
  2604.   "zcaron",
  2605.   "brokenbar",
  2606.   "Eth",
  2607.   "eth",
  2608.   "Yacute",
  2609.   "yacute",
  2610.   "Thorn",
  2611.   "thorn",
  2612.   "minus",
  2613.   "multiply",
  2614.   "onesuperior",
  2615.   "twosuperior",
  2616.   "threesuperior",
  2617.   "onehalf",
  2618.   "onequarter",
  2619.   "threequarters",
  2620.   "franc",
  2621.   "Gbreve",
  2622.   "gbreve",
  2623.   "Idot",
  2624.   "Scedilla",
  2625.   "scedilla",
  2626.   "Cacute",
  2627.   "cacute",
  2628.   "Ccaron",
  2629.   "ccaron",
  2630.   "dmacron"
  2631. };
  2632.  
  2633. enum T42FontIndexMode {
  2634.   t42FontModeUnicode,
  2635.   t42FontModeCharCode,
  2636.   t42FontModeCharCodeOffset,
  2637.   t42FontModeMacRoman
  2638. };
  2639.  
  2640. TrueTypeFontFile::TrueTypeFontFile(char *fileA, int lenA) {
  2641.   int pos, i, idx, n, length;
  2642.   Guint size, startPos, endPos;
  2643.  
  2644.   file = fileA;
  2645.   len = lenA;
  2646.  
  2647.   encoding = NULL;
  2648.  
  2649.   // read table directory
  2650.   nTables = getUShort(4);
  2651.   tableHdrs = (TTFontTableHdr *)gmalloc(nTables * sizeof(TTFontTableHdr));
  2652.   pos = 12;
  2653.   for (i = 0; i < nTables; ++i) {
  2654.     tableHdrs[i].tag[0] = getByte(pos+0);
  2655.     tableHdrs[i].tag[1] = getByte(pos+1);
  2656.     tableHdrs[i].tag[2] = getByte(pos+2);
  2657.     tableHdrs[i].tag[3] = getByte(pos+3);
  2658.     tableHdrs[i].checksum = getULong(pos+4);
  2659.     tableHdrs[i].offset = getULong(pos+8);
  2660.     tableHdrs[i].length = getULong(pos+12);
  2661.     pos += 16;
  2662.   }
  2663.  
  2664.   // check for tables that are required by both the TrueType spec
  2665.   // and the Type 42 spec
  2666.   if (seekTable("head") < 0 ||
  2667.       seekTable("hhea") < 0 ||
  2668.       seekTable("loca") < 0 ||
  2669.       seekTable("maxp") < 0 ||
  2670.       seekTable("glyf") < 0 ||
  2671.       seekTable("hmtx") < 0) {
  2672.     error(-1, "TrueType font file is missing a required table");
  2673.     return;
  2674.   }
  2675.  
  2676.   // some embedded TrueType fonts have an incorrect (too small) cmap
  2677.   // table size
  2678.   idx = seekTableIdx("cmap");
  2679.   if (idx >= 0) {
  2680.     pos = tableHdrs[idx].offset;
  2681.     n = getUShort(pos + 2);
  2682.     size = (Guint)(4 + 8 * n);
  2683.     for (i = 0; i < n; ++i) {
  2684.       startPos = getULong(pos + 4 + 8*i + 4);
  2685.       length = getUShort(pos + startPos + 2);
  2686.       endPos = startPos + length;
  2687.       if (endPos > size) {
  2688.         size = endPos;
  2689.       }
  2690.     }
  2691.     if ((mungedCmapSize = size > tableHdrs[idx].length)) {
  2692. #if 0 // don't bother printing this error message - it's too common
  2693.       error(-1, "Bad cmap table size in TrueType font");
  2694. #endif
  2695.       tableHdrs[idx].length = size;
  2696.     }
  2697.   } else {
  2698.     mungedCmapSize = gFalse;
  2699.   }
  2700.  
  2701.   // read the 'head' table
  2702.   pos = seekTable("head");
  2703.   bbox[0] = getShort(pos + 36);
  2704.   bbox[1] = getShort(pos + 38);
  2705.   bbox[2] = getShort(pos + 40);
  2706.   bbox[3] = getShort(pos + 42);
  2707.   locaFmt = getShort(pos + 50);
  2708.  
  2709.   // read the 'maxp' table
  2710.   pos = seekTable("maxp");
  2711.   nGlyphs = getUShort(pos + 4);
  2712. }
  2713.  
  2714. TrueTypeFontFile::~TrueTypeFontFile() {
  2715.   int i;
  2716.  
  2717.   if (encoding) {
  2718.     for (i = 0; i < 256; ++i) {
  2719.       gfree(encoding[i]);
  2720.     }
  2721.     gfree(encoding);
  2722.   }
  2723.   gfree(tableHdrs);
  2724. }
  2725.  
  2726. char *TrueTypeFontFile::getName() {
  2727.   return NULL;
  2728. }
  2729.  
  2730. char **TrueTypeFontFile::getEncoding() {
  2731.   int cmap[256];
  2732.   int nCmaps, cmapPlatform, cmapEncoding, cmapFmt;
  2733.   int cmapLen, cmapOffset, cmapFirst;
  2734.   int segCnt, segStart, segEnd, segDelta, segOffset;
  2735.   int pos, i, j, k;
  2736.   Guint fmt;
  2737.   GString *s;
  2738.   int stringIdx, stringPos, n;
  2739.  
  2740.   if (encoding) {
  2741.     return encoding;
  2742.   }
  2743.  
  2744.   //----- construct the (char code) -> (glyph idx) mapping
  2745.  
  2746.   // map everything to the missing glyph
  2747.   for (i = 0; i < 256; ++i) {
  2748.     cmap[i] = 0;
  2749.   }
  2750.  
  2751.   // look for the 'cmap' table
  2752.   if ((pos = seekTable("cmap")) >= 0) {
  2753.     nCmaps = getUShort(pos+2);
  2754.  
  2755.     // if the font has a Windows-symbol cmap, use it;
  2756.     // otherwise, use the first cmap in the table
  2757.     for (i = 0; i < nCmaps; ++i) {
  2758.       cmapPlatform = getUShort(pos + 4 + 8*i);
  2759.       cmapEncoding = getUShort(pos + 4 + 8*i + 2);
  2760.       if (cmapPlatform == 3 && cmapEncoding == 0) {
  2761.         break;
  2762.       }
  2763.     }
  2764.     if (i >= nCmaps) {
  2765.       i = 0;
  2766.       cmapPlatform = getUShort(pos + 4);
  2767.       cmapEncoding = getUShort(pos + 4 + 2);
  2768.     }
  2769.     pos += getULong(pos + 4 + 8*i + 4);
  2770.  
  2771.     // read the cmap
  2772.     cmapFmt = getUShort(pos);
  2773.     switch (cmapFmt) {
  2774.     case 0: // byte encoding table (Apple standard)
  2775.       cmapLen = getUShort(pos + 2);
  2776.       for (i = 0; i < cmapLen && i < 256; ++i) {
  2777.         cmap[i] = getByte(pos + 6 + i);
  2778.       }
  2779.       break;
  2780.     case 4: // segment mapping to delta values (Microsoft standard)
  2781.       if (cmapPlatform == 3 && cmapEncoding == 0) {
  2782.         // Windows-symbol uses char codes 0xf000 - 0xf0ff
  2783.         cmapOffset = 0xf000;
  2784.       } else {
  2785.         cmapOffset = 0;
  2786.       }
  2787.       segCnt = getUShort(pos + 6) / 2;
  2788.       for (i = 0; i < segCnt; ++i) {
  2789.         segEnd = getUShort(pos + 14 + 2*i);
  2790.         segStart = getUShort(pos + 16 + 2*segCnt + 2*i);
  2791.         segDelta = getUShort(pos + 16 + 4*segCnt + 2*i);
  2792.         segOffset = getUShort(pos + 16 + 6*segCnt + 2*i);
  2793.         if (segStart - cmapOffset <= 0xff &&
  2794.             segEnd - cmapOffset >= 0) {
  2795.           for (j = (segStart - cmapOffset >= 0) ? segStart : cmapOffset;
  2796.                j <= segEnd && j - cmapOffset <= 0xff;
  2797.                ++j) {
  2798.             if (segOffset == 0) {
  2799.               k = (j + segDelta) & 0xffff;
  2800.             } else {
  2801.               k = getUShort(pos + 16 + 6*segCnt + 2*i +
  2802.                             segOffset + 2 * (j - segStart));
  2803.               if (k != 0) {
  2804.                 k = (k + segDelta) & 0xffff;
  2805.               }
  2806.             }
  2807.             cmap[j - cmapOffset] = k;
  2808.           }
  2809.         }
  2810.       }
  2811.       break;
  2812.     case 6: // trimmed table mapping
  2813.       cmapFirst = getUShort(pos + 6);
  2814.       cmapLen = getUShort(pos + 8);
  2815.       for (i = cmapFirst; i < 256 && i < cmapFirst + cmapLen; ++i) {
  2816.         cmap[i] = getUShort(pos + 10 + 2*i);
  2817.       }
  2818.       break;
  2819.     default:
  2820.       error(-1, "Unimplemented cmap format (%d) in TrueType font file",
  2821.             cmapFmt);
  2822.       break;
  2823.     }
  2824.   }
  2825.  
  2826.   //----- construct the (glyph idx) -> (glyph name) mapping
  2827.   //----- and compute the (char code) -> (glyph name) mapping
  2828.  
  2829.   encoding = (char **)gmalloc(256 * sizeof(char *));
  2830.   for (i = 0; i < 256; ++i) {
  2831.     encoding[i] = NULL;
  2832.   }
  2833.  
  2834.   if ((pos = seekTable("post")) >= 0) {
  2835.     fmt = getULong(pos);
  2836.  
  2837.     // Apple font
  2838.     if (fmt == 0x00010000) {
  2839.       for (i = 0; i < 256; ++i) {
  2840.         j = (cmap[i] < 258) ? cmap[i] : 0;
  2841.         encoding[i] = copyString(macGlyphNames[j]);
  2842.       }
  2843.  
  2844.     // Microsoft font
  2845.     } else if (fmt == 0x00020000) {
  2846.       stringIdx = 0;
  2847.       stringPos = pos + 34 + 2*nGlyphs;
  2848.       for (i = 0; i < 256; ++i) {
  2849.         if (cmap[i] < nGlyphs) {
  2850.           j = getUShort(pos + 34 + 2 * cmap[i]);
  2851.           if (j < 258) {
  2852.             encoding[i] = copyString(macGlyphNames[j]);
  2853.           } else {
  2854.             j -= 258;
  2855.             if (j != stringIdx) {
  2856.               for (stringIdx = 0, stringPos = pos + 34 + 2*nGlyphs;
  2857.                    stringIdx < j;
  2858.                    ++stringIdx, stringPos += 1 + getByte(stringPos)) ;
  2859.             }
  2860.             n = getByte(stringPos);
  2861.             s = new GString(file + stringPos + 1, n);
  2862.             encoding[i] = copyString(s->getCString());
  2863.             delete s;
  2864.             ++stringIdx;
  2865.             stringPos += 1 + n;
  2866.           }
  2867.         } else {
  2868.           encoding[i] = copyString(macGlyphNames[0]);
  2869.         }
  2870.       }
  2871.  
  2872.     // Apple subset
  2873.     } else if (fmt == 0x000280000) {
  2874.       for (i = 0; i < 256; ++i) {
  2875.         if (cmap[i] < nGlyphs) {
  2876.           j = i + getChar(pos + 32 + cmap[i]);
  2877.         } else {
  2878.           j = 0;
  2879.         }
  2880.         encoding[i] = copyString(macGlyphNames[j]);
  2881.       }
  2882.  
  2883.     // Ugh, just assume the Apple glyph set
  2884.     } else {
  2885. //**** Colin Granville ****
  2886. #ifdef ACORN
  2887. // most seem to be winAnsi it's microsofts font after all
  2888.       int useWinAnsi=1;
  2889.       if (seekTable("name")>=0)
  2890.       {
  2891.         //bodge to quess encoding
  2892.         int pos=seekTable("name");
  2893.         int len=getShort(pos+14);
  2894.         char* n=file+getShort(pos+4)+pos;
  2895.         for (i=0;i<len;i++,n++)
  2896.         {
  2897.            if (*n=='+')
  2898.            {
  2899.              if (n[1]=='M' && n[2]=='S' && n[3]=='T' && n[4]=='T') useWinAnsi=0; 
  2900.              break;
  2901.            }
  2902.         }
  2903.       }
  2904.  
  2905.       if (useWinAnsi)
  2906.       {
  2907.         for (i = 0; i < 256; ++i) 
  2908.         {
  2909.              if (winAnsiEncoding[i]) 
  2910.                  encoding[i] = copyString(winAnsiEncoding[i]);
  2911.         }
  2912.       }
  2913.       else
  2914.       {
  2915.         for (i = 0; i < 256; ++i) 
  2916.         {
  2917.           j = (cmap[i] < 258) ? cmap[i] : 0;
  2918.           encoding[i] = copyString(macGlyphNames[j]);
  2919.         }
  2920.       }
  2921. #else
  2922.       for (i = 0; i < 256; ++i) {
  2923.         j = (cmap[i] < 258) ? cmap[i] : 0;
  2924.         encoding[i] = copyString(macGlyphNames[j]);
  2925.       }
  2926. #endif
  2927. //**** Colin Granville ****
  2928.     }
  2929.  
  2930.   // no "post" table: assume the Apple glyph set
  2931.   } else {
  2932.     for (i = 0; i < 256; ++i) {
  2933.       j = (cmap[i] < 258) ? cmap[i] : 0;
  2934.       encoding[i] = copyString(macGlyphNames[j]);
  2935.     }
  2936.   }
  2937.  
  2938.   return encoding;
  2939. }
  2940.  
  2941. void TrueTypeFontFile::convertToType42(char *name, char **encodingA,
  2942.                                        CharCodeToUnicode *toUnicode,
  2943.                                        GBool pdfFontHasEncoding,
  2944.                                        FontFileOutputFunc outputFunc,
  2945.                                        void *outputStream) {
  2946.   char buf[512];
  2947.  
  2948.   // write the header
  2949.   sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
  2950.   (*outputFunc)(outputStream, buf, strlen(buf));
  2951.  
  2952.   // begin the font dictionary
  2953.   (*outputFunc)(outputStream, "10 dict begin\n", 14);
  2954.   (*outputFunc)(outputStream, "/FontName /", 11);
  2955.   (*outputFunc)(outputStream, name, strlen(name));
  2956.   (*outputFunc)(outputStream, " def\n", 5);
  2957.   (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
  2958.   (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
  2959.   sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
  2960.           bbox[0], bbox[1], bbox[2], bbox[3]);
  2961.   (*outputFunc)(outputStream, buf, strlen(buf));
  2962.   (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
  2963.  
  2964.   // write the guts of the dictionary
  2965.   cvtEncoding(encodingA, pdfFontHasEncoding, outputFunc, outputStream);
  2966.   cvtCharStrings(encodingA, toUnicode, pdfFontHasEncoding,
  2967.                  outputFunc, outputStream);
  2968.   cvtSfnts(outputFunc, outputStream, NULL);
  2969.  
  2970.   // end the dictionary and define the font
  2971.   (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
  2972. }
  2973.  
  2974. void TrueTypeFontFile::convertToCIDType2(char *name, Gushort *cidMap,
  2975.                                          int nCIDs,
  2976.                                          FontFileOutputFunc outputFunc,
  2977.                                          void *outputStream) {
  2978.   char buf[512];
  2979.   Gushort cid;
  2980.   int i, j, k;
  2981.  
  2982.   // write the header
  2983.   sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
  2984.   (*outputFunc)(outputStream, buf, strlen(buf));
  2985.  
  2986.   // begin the font dictionary
  2987.   (*outputFunc)(outputStream, "20 dict begin\n", 14);
  2988.   (*outputFunc)(outputStream, "/CIDFontName /", 14);
  2989.   (*outputFunc)(outputStream, name, strlen(name));
  2990.   (*outputFunc)(outputStream, " def\n", 5);
  2991.   (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
  2992.   (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
  2993.   (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
  2994.   (*outputFunc)(outputStream, "  /Registry (Adobe) def\n", 24);
  2995.   (*outputFunc)(outputStream, "  /Ordering (Identity) def\n", 27);
  2996.   (*outputFunc)(outputStream, "  /Supplement 0 def\n", 20);
  2997.   (*outputFunc)(outputStream, "  end def\n", 10);
  2998.   (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
  2999.   if (cidMap) {
  3000.     sprintf(buf, "/CIDCount %d def\n", nCIDs);
  3001.     (*outputFunc)(outputStream, buf, strlen(buf));
  3002.     if (nCIDs > 32767) {
  3003.       (*outputFunc)(outputStream, "/CIDMap [", 9);
  3004.       for (i = 0; i < nCIDs; i += 32768 - 16) {
  3005.         (*outputFunc)(outputStream, "<\n", 2);
  3006.         for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
  3007.           (*outputFunc)(outputStream, "  ", 2);
  3008.           for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
  3009.             cid = cidMap[i+j+k];
  3010.             sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
  3011.             (*outputFunc)(outputStream, buf, strlen(buf));
  3012.           }
  3013.           (*outputFunc)(outputStream, "\n", 1);
  3014.         }
  3015.         (*outputFunc)(outputStream, "  >", 3);
  3016.       }
  3017.       (*outputFunc)(outputStream, "\n", 1);
  3018.       (*outputFunc)(outputStream, "] def\n", 6);
  3019.     } else {
  3020.       (*outputFunc)(outputStream, "/CIDMap <\n", 10);
  3021.       for (i = 0; i < nCIDs; i += 16) {
  3022.         (*outputFunc)(outputStream, "  ", 2);
  3023.         for (j = 0; j < 16 && i+j < nCIDs; ++j) {
  3024.           cid = cidMap[i+j];
  3025.           sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
  3026.           (*outputFunc)(outputStream, buf, strlen(buf));
  3027.         }
  3028.         (*outputFunc)(outputStream, "\n", 1);
  3029.       }
  3030.       (*outputFunc)(outputStream, "> def\n", 6);
  3031.     }
  3032.   } else {
  3033.     // direct mapping - just fill the string(s) with s[i]=i
  3034.     sprintf(buf, "/CIDCount %d def\n", nGlyphs);
  3035.     (*outputFunc)(outputStream, buf, strlen(buf));
  3036.     if (nGlyphs > 32767) {
  3037.       (*outputFunc)(outputStream, "/CIDMap [\n", 10);
  3038.       for (i = 0; i < nGlyphs; i += 32767) {
  3039.         j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
  3040.         sprintf(buf, "  %d string 0 1 %d {\n", 2 * j, j - 1);
  3041.         (*outputFunc)(outputStream, buf, strlen(buf));
  3042.         sprintf(buf, "    2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
  3043.         (*outputFunc)(outputStream, buf, strlen(buf));
  3044.         sprintf(buf, "    1 index exch dup 2 mul 1 add exch %d add"
  3045.                 " 255 and put\n", i);
  3046.         (*outputFunc)(outputStream, buf, strlen(buf));
  3047.         (*outputFunc)(outputStream, "  } for\n", 8);
  3048.       }
  3049.       (*outputFunc)(outputStream, "] def\n", 6);
  3050.     } else {
  3051.       sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs);
  3052.       (*outputFunc)(outputStream, buf, strlen(buf));
  3053.       sprintf(buf, "  0 1 %d {\n", nGlyphs - 1);
  3054.       (*outputFunc)(outputStream, buf, strlen(buf));
  3055.       (*outputFunc)(outputStream,
  3056.                     "    2 copy dup 2 mul exch -8 bitshift put\n", 42);
  3057.       (*outputFunc)(outputStream,
  3058.                     "    1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
  3059.       (*outputFunc)(outputStream, "  } for\n", 8);
  3060.       (*outputFunc)(outputStream, "def\n", 4);
  3061.     }
  3062.   }
  3063.   (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
  3064.   sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
  3065.           bbox[0], bbox[1], bbox[2], bbox[3]);
  3066.   (*outputFunc)(outputStream, buf, strlen(buf));
  3067.   (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
  3068.   (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
  3069.   (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
  3070.   (*outputFunc)(outputStream, "  /.notdef 0 def\n", 17);
  3071.   (*outputFunc)(outputStream, "  end readonly def\n", 19);
  3072.  
  3073.   // write the guts of the dictionary
  3074.   cvtSfnts(outputFunc, outputStream, NULL);
  3075.  
  3076.   // end the dictionary and define the font
  3077.   (*outputFunc)(outputStream,
  3078.                 "CIDFontName currentdict end /CIDFont defineresource pop\n",
  3079.                 56);
  3080. }
  3081.  
  3082. void TrueTypeFontFile::convertToType0(char *name, Gushort *cidMap,
  3083.                                       int nCIDs,
  3084.                                       FontFileOutputFunc outputFunc,
  3085.                                       void *outputStream) {
  3086.   char buf[512];
  3087.   GString *sfntsName;
  3088.   int n, i, j;
  3089.  
  3090.   // write the Type 42 sfnts array
  3091.   sfntsName = (new GString(name))->append("_sfnts");
  3092.   cvtSfnts(outputFunc, outputStream, sfntsName);
  3093.   delete sfntsName;
  3094.  
  3095.   // write the descendant Type 42 fonts
  3096.   n = cidMap ? nCIDs : nGlyphs;
  3097.   for (i = 0; i < n; i += 256) {
  3098.     (*outputFunc)(outputStream, "10 dict begin\n", 14);
  3099.     (*outputFunc)(outputStream, "/FontName /", 11);
  3100.     (*outputFunc)(outputStream, name, strlen(name));
  3101.     sprintf(buf, "_%02x def\n", i >> 8);
  3102.     (*outputFunc)(outputStream, buf, strlen(buf));
  3103.     (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
  3104.     (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
  3105.     sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
  3106.             bbox[0], bbox[1], bbox[2], bbox[3]);
  3107.     (*outputFunc)(outputStream, buf, strlen(buf));
  3108.     (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
  3109.     (*outputFunc)(outputStream, "/sfnts ", 7);
  3110.     (*outputFunc)(outputStream, name, strlen(name));
  3111.     (*outputFunc)(outputStream, "_sfnts def\n", 11);
  3112.     (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
  3113.     for (j = 0; j < 256 && i+j < n; ++j) {
  3114.       sprintf(buf, "dup %d /c%02x put\n", j, j);
  3115.       (*outputFunc)(outputStream, buf, strlen(buf));
  3116.     }
  3117.     (*outputFunc)(outputStream, "readonly def\n", 13);
  3118.     (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
  3119.     (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
  3120.     for (j = 0; j < 256 && i+j < n; ++j) {
  3121.       sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
  3122.       (*outputFunc)(outputStream, buf, strlen(buf));
  3123.     }
  3124.     (*outputFunc)(outputStream, "end readonly def\n", 17);
  3125.     (*outputFunc)(outputStream,
  3126.                   "FontName currentdict end definefont pop\n", 40);
  3127.   }
  3128.  
  3129.   // write the Type 0 parent font
  3130.   (*outputFunc)(outputStream, "16 dict begin\n", 14);
  3131.   (*outputFunc)(outputStream, "/FontName /", 11);
  3132.   (*outputFunc)(outputStream, name, strlen(name));
  3133.   (*outputFunc)(outputStream, " def\n", 5);
  3134.   (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
  3135.   (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
  3136.   (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
  3137.   (*outputFunc)(outputStream, "/Encoding [\n", 12);
  3138.   for (i = 0; i < n; i += 256) {
  3139.     sprintf(buf, "%d\n", i >> 8);
  3140.     (*outputFunc)(outputStream, buf, strlen(buf));
  3141.   }
  3142.   (*outputFunc)(outputStream, "] def\n", 6);
  3143.   (*outputFunc)(outputStream, "/FDepVector [\n", 14);
  3144.   for (i = 0; i < n; i += 256) {
  3145.     (*outputFunc)(outputStream, "/", 1);
  3146.     (*outputFunc)(outputStream, name, strlen(name));
  3147.     sprintf(buf, "_%02x findfont\n", i >> 8);
  3148.     (*outputFunc)(outputStream, buf, strlen(buf));
  3149.   }
  3150.   (*outputFunc)(outputStream, "] def\n", 6);
  3151.   (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
  3152. }
  3153.  
  3154. int TrueTypeFontFile::getByte(int pos) {
  3155.   if (pos < 0 || pos >= len) {
  3156.     return 0;
  3157.   }
  3158.   return file[pos] & 0xff;
  3159. }
  3160.  
  3161. int TrueTypeFontFile::getChar(int pos) {
  3162.   int x;
  3163.  
  3164.   if (pos < 0 || pos >= len) {
  3165.     return 0;
  3166.   }
  3167.   x = file[pos] & 0xff;
  3168.   if (x & 0x80)
  3169.     x |= 0xffffff00;
  3170.   return x;
  3171. }
  3172.  
  3173. int TrueTypeFontFile::getUShort(int pos) {
  3174.   int x;
  3175.  
  3176.   if (pos < 0 || pos+1 >= len) {
  3177.     return 0;
  3178.   }
  3179.   x = file[pos] & 0xff;
  3180.   x = (x << 8) + (file[pos+1] & 0xff);
  3181.   return x;
  3182. }
  3183.  
  3184. int TrueTypeFontFile::getShort(int pos) {
  3185.   int x;
  3186.  
  3187.   if (pos < 0 || pos+1 >= len) {
  3188.     return 0;
  3189.   }
  3190.   x = file[pos] & 0xff;
  3191.   x = (x << 8) + (file[pos+1] & 0xff);
  3192.   if (x & 0x8000)
  3193.     x |= 0xffff0000;
  3194.   return x;
  3195. }
  3196.  
  3197. Guint TrueTypeFontFile::getULong(int pos) {
  3198.   int x;
  3199.  
  3200.   if (pos < 0 || pos+3 >= len) {
  3201.     return 0;
  3202.   }
  3203.   x = file[pos] & 0xff;
  3204.   x = (x << 8) + (file[pos+1] & 0xff);
  3205.   x = (x << 8) + (file[pos+2] & 0xff);
  3206.   x = (x << 8) + (file[pos+3] & 0xff);
  3207.   return x;
  3208. }
  3209.  
  3210. double TrueTypeFontFile::getFixed(int pos) {
  3211.   int x, y;
  3212.  
  3213.   x = getShort(pos);
  3214.   y = getUShort(pos+2);
  3215.   return (double)x + (double)y / 65536;
  3216. }
  3217.  
  3218. int TrueTypeFontFile::seekTable(char *tag) {
  3219.   int i;
  3220.  
  3221.   for (i = 0; i < nTables; ++i) {
  3222.     if (!strncmp(tableHdrs[i].tag, tag, 4)) {
  3223.       return tableHdrs[i].offset;
  3224.     }
  3225.   }
  3226.   return -1;
  3227. }
  3228.  
  3229. int TrueTypeFontFile::seekTableIdx(char *tag) {
  3230.   int i;
  3231.  
  3232.   for (i = 0; i < nTables; ++i) {
  3233.     if (!strncmp(tableHdrs[i].tag, tag, 4)) {
  3234.       return i;
  3235.     }
  3236.   }
  3237.   return -1;
  3238. }
  3239.  
  3240. void TrueTypeFontFile::cvtEncoding(char **encodingA, GBool pdfFontHasEncoding,
  3241.                                    FontFileOutputFunc outputFunc,
  3242.                                    void *outputStream) {
  3243.   char *name;
  3244.   char buf[64];
  3245.   int i;
  3246.  
  3247.   (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
  3248.   if (pdfFontHasEncoding) {
  3249.     for (i = 0; i < 256; ++i) {
  3250.       if (!(name = encodingA[i])) {
  3251.         name = ".notdef";
  3252.       }
  3253.       sprintf(buf, "dup %d /", i);
  3254.       (*outputFunc)(outputStream, buf, strlen(buf));
  3255.       (*outputFunc)(outputStream, name, strlen(name));
  3256.       (*outputFunc)(outputStream, " put\n", 5);
  3257.     }
  3258.   } else {
  3259.     for (i = 0; i < 256; ++i) {
  3260.       sprintf(buf, "dup %d /c%02x put\n", i, i);
  3261.       (*outputFunc)(outputStream, buf, strlen(buf));
  3262.     }
  3263.   }
  3264.   (*outputFunc)(outputStream, "readonly def\n", 13);
  3265. }
  3266.  
  3267. void TrueTypeFontFile::cvtCharStrings(char **encodingA,
  3268.                                       CharCodeToUnicode *toUnicode,
  3269.                                       GBool pdfFontHasEncoding,
  3270.                                       FontFileOutputFunc outputFunc,
  3271.                                       void *outputStream) {
  3272.   int unicodeCmap, macRomanCmap, msSymbolCmap;
  3273.   int nCmaps, cmapPlatform, cmapEncoding, cmapFmt, cmapOffset;
  3274.   T42FontIndexMode mode;
  3275.   char *name;
  3276.   char buf[64], buf2[16];
  3277.   Unicode u;
  3278.   int pos, i, j, k;
  3279.  
  3280.   // always define '.notdef'
  3281.   (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
  3282.   (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
  3283.  
  3284.   // if there's no 'cmap' table, punt
  3285.   if ((pos = seekTable("cmap")) < 0) {
  3286.     goto err;
  3287.   }
  3288.  
  3289.   // To match up with the Adobe-defined behaviour, we choose a cmap
  3290.   // like this:
  3291.   // 1. If the PDF font has an encoding:
  3292.   //    1a. If the TrueType font has a Microsoft Unicode cmap, use it,
  3293.   //        and use the Unicode indexes, not the char codes.
  3294.   //    1b. If the TrueType font has a Macintosh Roman cmap, use it,
  3295.   //        and reverse map the char names through MacRomanEncoding to
  3296.   //        get char codes.
  3297.   // 2. If the PDF font does not have an encoding:
  3298.   //    2a. If the TrueType font has a Macintosh Roman cmap, use it,
  3299.   //        and use char codes directly.
  3300.   //    2b. If the TrueType font has a Microsoft Symbol cmap, use it,
  3301.   //        and use (0xf000 + char code).
  3302.   // 3. If none of these rules apply, use the first cmap and hope for
  3303.   //    the best (this shouldn't happen).
  3304.   nCmaps = getUShort(pos+2);
  3305.   unicodeCmap = macRomanCmap = msSymbolCmap = -1;
  3306.   cmapOffset = 0;
  3307.   for (i = 0; i < nCmaps; ++i) {
  3308.     cmapPlatform = getUShort(pos + 4 + 8*i);
  3309.     cmapEncoding = getUShort(pos + 4 + 8*i + 2);
  3310.     if (cmapPlatform == 3 && cmapEncoding == 1) {
  3311.       unicodeCmap = i;
  3312.     } else if (cmapPlatform == 1 && cmapEncoding == 0) {
  3313.       macRomanCmap = i;
  3314.     } else if (cmapPlatform == 3 && cmapEncoding == 0) {
  3315.       msSymbolCmap = i;
  3316.     }
  3317.   }
  3318.   i = 0;
  3319.   mode = t42FontModeCharCode;
  3320.   if (pdfFontHasEncoding) {
  3321.     if (unicodeCmap >= 0) {
  3322.       i = unicodeCmap;
  3323.       mode = t42FontModeUnicode;
  3324.     } else if (macRomanCmap >= 0) {
  3325.       i = macRomanCmap;
  3326.       mode = t42FontModeMacRoman;
  3327.     }
  3328.   } else {
  3329.     if (macRomanCmap >= 0) {
  3330.       i = macRomanCmap;
  3331.       mode = t42FontModeCharCode;
  3332.     } else if (msSymbolCmap >= 0) {
  3333.       i = msSymbolCmap;
  3334.       mode = t42FontModeCharCodeOffset;
  3335.       cmapOffset = 0xf000;
  3336.     }
  3337.   }
  3338.   cmapPlatform = getUShort(pos + 4 + 8*i);
  3339.   cmapEncoding = getUShort(pos + 4 + 8*i + 2);
  3340.   pos += getULong(pos + 4 + 8*i + 4);
  3341.   cmapFmt = getUShort(pos);
  3342.   if (cmapFmt != 0 && cmapFmt != 4 && cmapFmt != 6) {
  3343.     error(-1, "Unimplemented cmap format (%d) in TrueType font file",
  3344.           cmapFmt);
  3345.     goto err;
  3346.   }
  3347.  
  3348.   // map char name to glyph index:
  3349.   // 1. use encoding to map name to char code
  3350.   // 2. use cmap to map char code to glyph index
  3351.   j = 0; // make gcc happy
  3352.   for (i = 0; i < 256; ++i) {
  3353.     if (pdfFontHasEncoding) {
  3354.       name = encodingA[i];
  3355.     } else {
  3356.       sprintf(buf2, "c%02x", i);
  3357.       name = buf2;
  3358.     }
  3359.     if (name && strcmp(name, ".notdef")) {
  3360.       switch (mode) {
  3361.       case t42FontModeUnicode:
  3362.         toUnicode->mapToUnicode((CharCode)i, &u, 1);
  3363.         j = (int)u;
  3364.         break;
  3365.       case t42FontModeCharCode:
  3366.         j = i;
  3367.         break;
  3368.       case t42FontModeCharCodeOffset:
  3369.         j = cmapOffset + i;
  3370.         break;
  3371.       case t42FontModeMacRoman:
  3372.         j = globalParams->getMacRomanCharCode(name);
  3373.         break;
  3374.       }
  3375.       // note: Distiller (maybe Adobe's PS interpreter in general)
  3376.       // doesn't like TrueType fonts that have CharStrings entries
  3377.       // which point to nonexistent glyphs, hence the (k < nGlyphs)
  3378.       // test
  3379.       if ((k = getCmapEntry(cmapFmt, pos, j)) > 0 &&
  3380.           k < nGlyphs) {
  3381.         (*outputFunc)(outputStream, "/", 1);
  3382.         (*outputFunc)(outputStream, name, strlen(name));
  3383.         sprintf(buf, " %d def\n", k);
  3384.         (*outputFunc)(outputStream, buf, strlen(buf));
  3385.       }
  3386.     }
  3387.   }
  3388.  
  3389.  err:
  3390.   (*outputFunc)(outputStream, "end readonly def\n", 17);
  3391. }
  3392.  
  3393. int TrueTypeFontFile::getCmapEntry(int cmapFmt, int pos, int code) {
  3394.   int cmapLen, cmapFirst;
  3395.   int segCnt, segEnd, segStart, segDelta, segOffset;
  3396.   int a, b, m, i;
  3397.  
  3398.   switch (cmapFmt) {
  3399.   case 0: // byte encoding table (Apple standard)
  3400.     cmapLen = getUShort(pos + 2);
  3401.     if (code >= cmapLen) {
  3402.       return 0;
  3403.     }
  3404.     return getByte(pos + 6 + code);
  3405.  
  3406.   case 4: // segment mapping to delta values (Microsoft standard)
  3407.     segCnt = getUShort(pos + 6) / 2;
  3408.     a = -1;
  3409.     b = segCnt - 1;
  3410.     segEnd = getUShort(pos + 14 + 2*b);
  3411.     if (code > segEnd) {
  3412.       // malformed font -- the TrueType spec requires the last segEnd
  3413.       // to be 0xffff
  3414.       return 0;
  3415.     }
  3416.     // invariant: seg[a].end < code <= seg[b].end
  3417.     while (b - a > 1) {
  3418.       m = (a + b) / 2;
  3419.       segEnd = getUShort(pos + 14 + 2*m);
  3420.       if (segEnd < code) {
  3421.         a = m;
  3422.       } else {
  3423.         b = m;
  3424.       }
  3425.     }
  3426.     segStart = getUShort(pos + 16 + 2*segCnt + 2*b);
  3427.     segDelta = getUShort(pos + 16 + 4*segCnt + 2*b);
  3428.     segOffset = getUShort(pos + 16 + 6*segCnt + 2*b);
  3429.     if (segOffset == 0) {
  3430.       i = (code + segDelta) & 0xffff;
  3431.     } else {
  3432.       i = getUShort(pos + 16 + 6*segCnt + 2*b +
  3433.                     segOffset + 2 * (code - segStart));
  3434.       if (i != 0) {
  3435.         i = (i + segDelta) & 0xffff;
  3436.       }
  3437.     }
  3438.     return i;
  3439.  
  3440.   case 6: // trimmed table mapping
  3441.     cmapFirst = getUShort(pos + 6);
  3442.     cmapLen = getUShort(pos + 8);
  3443.     if (code < cmapFirst || code >= cmapFirst + cmapLen) {
  3444.       return 0;
  3445.     }
  3446.     return getUShort(pos + 10 + 2*(code - cmapFirst));
  3447.  
  3448.   default:
  3449.     // shouldn't happen - this is checked earlier
  3450.     break;
  3451.   }
  3452.   return 0;
  3453. }
  3454.  
  3455. void TrueTypeFontFile::cvtSfnts(FontFileOutputFunc outputFunc,
  3456.                                 void *outputStream, GString *name) {
  3457.   TTFontTableHdr newTableHdrs[nT42Tables];
  3458.   char tableDir[12 + nT42Tables*16];
  3459.   char headTable[54];
  3460.   int *origLocaTable;
  3461.   char *locaTable;
  3462.   int nNewTables;
  3463.   Guint checksum;
  3464.   int pos, glyfPos, length, glyphLength, pad;
  3465.   int i, j, k;
  3466.  
  3467.   // construct the 'head' table, zero out the font checksum
  3468.   memcpy(headTable, file + seekTable("head"), 54);
  3469.   headTable[8] = headTable[9] = headTable[10] = headTable[11] = (char)0;
  3470.  
  3471.   // read the original 'loca' table and construct the new one
  3472.   // (pad each glyph out to a multiple of 4 bytes)
  3473.   origLocaTable = (int *)gmalloc((nGlyphs + 1) * sizeof(int));
  3474.   pos = seekTable("loca");
  3475.   for (i = 0; i <= nGlyphs; ++i) {
  3476.     if (locaFmt) {
  3477.       origLocaTable[i] = getULong(pos + 4*i);
  3478.     } else {
  3479.       origLocaTable[i] = 2 * getUShort(pos + 2*i);
  3480.     }
  3481.   }
  3482.   locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
  3483.   if (locaFmt) {
  3484.     locaTable[0] = locaTable[1] = locaTable[2] = locaTable[3] = 0;
  3485.   } else {
  3486.     locaTable[0] = locaTable[1] = 0;
  3487.   }
  3488.   pos = 0;
  3489.   for (i = 1; i <= nGlyphs; ++i) {
  3490.     length = origLocaTable[i] - origLocaTable[i-1];
  3491.     if (length & 3) {
  3492.       length += 4 - (length & 3);
  3493.     }
  3494.     pos += length;
  3495.     if (locaFmt) {
  3496.       locaTable[4*i  ] = (char)(pos >> 24);
  3497.       locaTable[4*i+1] = (char)(pos >> 16);
  3498.       locaTable[4*i+2] = (char)(pos >>  8);
  3499.       locaTable[4*i+3] = (char) pos;
  3500.     } else {
  3501.       locaTable[2*i  ] = (char)(pos >> 9);
  3502.       locaTable[2*i+1] = (char)(pos >> 1);
  3503.     }
  3504.   }
  3505.  
  3506.   // count the number of tables
  3507.   nNewTables = 0;
  3508.   for (i = 0; i < nT42Tables; ++i) {
  3509.     if (t42Tables[i].required ||
  3510.         seekTable(t42Tables[i].tag) >= 0) {
  3511.       ++nNewTables;
  3512.     }
  3513.   }
  3514.  
  3515.   // construct the new table headers, including table checksums
  3516.   // (pad each table out to a multiple of 4 bytes)
  3517.   pos = 12 + nNewTables*16;
  3518.   k = 0;
  3519.   for (i = 0; i < nT42Tables; ++i) {
  3520.     length = -1;
  3521.     checksum = 0; // make gcc happy
  3522.     if (i == t42HeadTable) {
  3523.       length = 54;
  3524.       checksum = computeTableChecksum(headTable, 54);
  3525.     } else if (i == t42LocaTable) {
  3526.       length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
  3527.       checksum = computeTableChecksum(locaTable, length);
  3528.     } else if (i == t42GlyfTable) {
  3529.       length = 0;
  3530.       checksum = 0;
  3531.       glyfPos = seekTable("glyf");
  3532.       for (j = 0; j < nGlyphs; ++j) {
  3533.         glyphLength = origLocaTable[j+1] - origLocaTable[j];
  3534.         pad = (glyphLength & 3) ? 4 - (glyphLength & 3) : 0;
  3535.         length += glyphLength + pad;
  3536.         checksum += computeTableChecksum(file + glyfPos + origLocaTable[j],
  3537.                                          glyphLength);
  3538.       }
  3539.     } else {
  3540.       if ((j = seekTableIdx(t42Tables[i].tag)) >= 0) {
  3541.         length = tableHdrs[j].length;
  3542.         checksum = computeTableChecksum(file + tableHdrs[j].offset, length);
  3543.       } else if (t42Tables[i].required) {
  3544.         error(-1, "Embedded TrueType font is missing a required table ('%s')",
  3545.               t42Tables[i].tag);
  3546.         length = 0;
  3547.         checksum = 0;
  3548.       }
  3549.     }
  3550.     if (length >= 0) {
  3551.       strncpy(newTableHdrs[k].tag, t42Tables[i].tag, 4);
  3552.       newTableHdrs[k].checksum = checksum;
  3553.       newTableHdrs[k].offset = pos;
  3554.       newTableHdrs[k].length = length;
  3555.       pad = (length & 3) ? 4 - (length & 3) : 0;
  3556.       pos += length + pad;
  3557.       ++k;
  3558.     }
  3559.   }
  3560.  
  3561.   // construct the table directory
  3562.   tableDir[0] = 0x00;           // sfnt version
  3563.   tableDir[1] = 0x01;
  3564.   tableDir[2] = 0x00;
  3565.   tableDir[3] = 0x00;
  3566.   tableDir[4] = 0;              // numTables
  3567.   tableDir[5] = nNewTables;
  3568.   tableDir[6] = 0;              // searchRange
  3569.   tableDir[7] = (char)128;
  3570.   tableDir[8] = 0;              // entrySelector
  3571.   tableDir[9] = 3;
  3572.   tableDir[10] = 0;             // rangeShift
  3573.   tableDir[11] = (char)(16 * nNewTables - 128);
  3574.   pos = 12;
  3575.   for (i = 0; i < nNewTables; ++i) {
  3576.     tableDir[pos   ] = newTableHdrs[i].tag[0];
  3577.     tableDir[pos+ 1] = newTableHdrs[i].tag[1];
  3578.     tableDir[pos+ 2] = newTableHdrs[i].tag[2];
  3579.     tableDir[pos+ 3] = newTableHdrs[i].tag[3];
  3580.     tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
  3581.     tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
  3582.     tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >>  8);
  3583.     tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
  3584.     tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
  3585.     tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
  3586.     tableDir[pos+10] = (char)(newTableHdrs[i].offset >>  8);
  3587.     tableDir[pos+11] = (char) newTableHdrs[i].offset;
  3588.     tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
  3589.     tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
  3590.     tableDir[pos+14] = (char)(newTableHdrs[i].length >>  8);
  3591.     tableDir[pos+15] = (char) newTableHdrs[i].length;
  3592.     pos += 16;
  3593.   }
  3594.  
  3595.   // compute the font checksum and store it in the head table
  3596.   checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
  3597.   for (i = 0; i < nNewTables; ++i) {
  3598.     checksum += newTableHdrs[i].checksum;
  3599.   }
  3600.   checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
  3601.   headTable[ 8] = (char)(checksum >> 24);
  3602.   headTable[ 9] = (char)(checksum >> 16);
  3603.   headTable[10] = (char)(checksum >>  8);
  3604.   headTable[11] = (char) checksum;
  3605.  
  3606.   // start the sfnts array
  3607.   if (name) {
  3608.     (*outputFunc)(outputStream, "/", 1);
  3609.     (*outputFunc)(outputStream, name->getCString(), name->getLength());
  3610.     (*outputFunc)(outputStream, " [\n", 3);
  3611.   } else {
  3612.     (*outputFunc)(outputStream, "/sfnts [\n", 9);
  3613.   }
  3614.  
  3615.   // write the table directory
  3616.   dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
  3617.  
  3618.   // write the tables
  3619.   for (i = 0; i < nNewTables; ++i) {
  3620.     if (i == t42HeadTable) {
  3621.       dumpString(headTable, 54, outputFunc, outputStream);
  3622.     } else if (i == t42LocaTable) {
  3623.       length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
  3624.       dumpString(locaTable, length, outputFunc, outputStream);
  3625.     } else if (i == t42GlyfTable) {
  3626.       glyfPos = seekTable("glyf");
  3627.       for (j = 0; j < nGlyphs; ++j) {
  3628.         length = origLocaTable[j+1] - origLocaTable[j];
  3629.         if (length > 0) {
  3630.           dumpString(file + glyfPos + origLocaTable[j], length,
  3631.                      outputFunc, outputStream);
  3632.         }
  3633.       }
  3634.     } else {
  3635.       // length == 0 means the table is missing and the error was
  3636.       // already reported during the construction of the table
  3637.       // headers
  3638.       if ((length = newTableHdrs[i].length) > 0) {
  3639.         dumpString(file + seekTable(t42Tables[i].tag), length,
  3640.                    outputFunc, outputStream);
  3641.       }
  3642.     }
  3643.   }
  3644.  
  3645.   // end the sfnts array
  3646.   (*outputFunc)(outputStream, "] def\n", 6);
  3647.  
  3648.   gfree(origLocaTable);
  3649.   gfree(locaTable);
  3650. }
  3651.  
  3652. void TrueTypeFontFile::dumpString(char *s, int length,
  3653.                                   FontFileOutputFunc outputFunc,
  3654.                                   void *outputStream) {
  3655.   char buf[64];
  3656.   int pad, i, j;
  3657.  
  3658.   (*outputFunc)(outputStream, "<", 1);
  3659.   for (i = 0; i < length; i += 32) {
  3660.     for (j = 0; j < 32 && i+j < length; ++j) {
  3661.       sprintf(buf, "%02X", s[i+j] & 0xff);
  3662.       (*outputFunc)(outputStream, buf, strlen(buf));
  3663.     }
  3664.     if (i % (65536 - 32) == 65536 - 64) {
  3665.       (*outputFunc)(outputStream, ">\n<", 3);
  3666.     } else if (i+32 < length) {
  3667.       (*outputFunc)(outputStream, "\n", 1);
  3668.     }
  3669.   }
  3670.   if (length & 3) {
  3671.     pad = 4 - (length & 3);
  3672.     for (i = 0; i < pad; ++i) {
  3673.       (*outputFunc)(outputStream, "00", 2);
  3674.     }
  3675.   }
  3676.   // add an extra zero byte because the Adobe Type 42 spec says so
  3677.   (*outputFunc)(outputStream, "00>\n", 4);
  3678. }
  3679.  
  3680. Guint TrueTypeFontFile::computeTableChecksum(char *data, int length) {
  3681.   Guint checksum, word;
  3682.   int i;
  3683.  
  3684.   checksum = 0;
  3685.   for (i = 0; i+3 < length; i += 4) {
  3686.     word = ((data[i  ] & 0xff) << 24) +
  3687.            ((data[i+1] & 0xff) << 16) +
  3688.            ((data[i+2] & 0xff) <<  8) +
  3689.             (data[i+3] & 0xff);
  3690.     checksum += word;
  3691.   }
  3692.   if (length & 3) {
  3693.     word = 0;
  3694.     i = length & ~3;
  3695.     switch (length & 3) {
  3696.     case 3:
  3697.       word |= (data[i+2] & 0xff) <<  8;
  3698.     case 2:
  3699.       word |= (data[i+1] & 0xff) << 16;
  3700.     case 1:
  3701.       word |= (data[i  ] & 0xff) << 24;
  3702.       break;
  3703.     }
  3704.     checksum += word;
  3705.   }
  3706.   return checksum;
  3707. }
  3708.  
  3709. void TrueTypeFontFile::writeTTF(FILE *out) {
  3710.   static char cmapTab[20] = {
  3711.     0, 0,                       // table version number
  3712.     0, 1,                       // number of encoding tables
  3713.     0, 1,                       // platform ID
  3714.     0, 0,                       // encoding ID
  3715.     0, 0, 0, 12,                // offset of subtable
  3716.     0, 0,                       // subtable format
  3717.     0, 1,                       // subtable length
  3718.     0, 1,                       // subtable version
  3719.     0,                          // map char 0 -> glyph 0
  3720.     0                           // pad to multiple of four bytes
  3721.   };
  3722.   static char nameTab[8] = {
  3723.     0, 0,                       // format
  3724.     0, 0,                       // number of name records
  3725.     0, 6,                       // offset to start of string storage
  3726.     0, 0                        // pad to multiple of four bytes
  3727.   };
  3728.   static char postTab[32] = {
  3729.     0, 1, 0, 0,                 // format
  3730.     0, 0, 0, 0,                 // italic angle
  3731.     0, 0,                       // underline position
  3732.     0, 0,                       // underline thickness
  3733.     0, 0, 0, 0,                 // fixed pitch
  3734.     0, 0, 0, 0,                 // min Type 42 memory
  3735.     0, 0, 0, 0,                 // max Type 42 memory
  3736.     0, 0, 0, 0,                 // min Type 1 memory
  3737.     0, 0, 0, 0                  // max Type 1 memory
  3738.   };
  3739.   GBool haveCmap, haveName, havePost;
  3740.   GBool dirCmap, dirName, dirPost;
  3741.   int nNewTables, nAllTables, pad;
  3742.   char *tableDir;
  3743.   Guint t, pos;
  3744.   int i, j;
  3745.  
  3746.   // check for missing tables
  3747.   haveCmap = seekTable("cmap") >= 0;
  3748.   haveName = seekTable("name") >= 0;
  3749.   havePost = seekTable("post") >= 0;
  3750.   nNewTables = (haveCmap ? 0 : 1) + (haveName ? 0 : 1) + (havePost ? 0 : 1);
  3751.   if (!nNewTables && !mungedCmapSize) {
  3752.     // none are missing - write the TTF file as is
  3753.     fwrite(file, 1, len, out);
  3754.     return;
  3755.   }
  3756.  
  3757.   // construct the new table directory
  3758.   nAllTables = nTables + nNewTables;
  3759.   tableDir = (char *)gmalloc(12 + nAllTables * 16);
  3760.   memcpy(tableDir, file, 12 + nTables * 16);
  3761.   tableDir[4] = (char)((nAllTables >> 8) & 0xff);
  3762.   tableDir[5] = (char)(nAllTables & 0xff);
  3763.   for (i = -1, t = (Guint)nAllTables; t; ++i, t >>= 1) ;
  3764.   t = 1 << (4 + i);
  3765.   tableDir[6] = (char)((t >> 8) & 0xff);
  3766.   tableDir[7] = (char)(t & 0xff);
  3767.   tableDir[8] = (char)((i >> 8) & 0xff);
  3768.   tableDir[9] = (char)(i & 0xff);
  3769.   t = nAllTables * 16 - t;
  3770.   tableDir[10] = (char)((t >> 8) & 0xff);
  3771.   tableDir[11] = (char)(t & 0xff);
  3772.   dirCmap = haveCmap;
  3773.   dirName = haveName;
  3774.   dirPost = havePost;
  3775.   j = 0;
  3776.   pad = (len & 3) ? 4 - (len & 3) : 0;
  3777.   pos = len + pad + 16 * nNewTables;
  3778.   for (i = 0; i < nTables; ++i) {
  3779.     if (!dirCmap && strncmp(tableHdrs[i].tag, "cmap", 4) > 0) {
  3780.       tableDir[12 + 16*j     ] = 'c';
  3781.       tableDir[12 + 16*j +  1] = 'm';
  3782.       tableDir[12 + 16*j +  2] = 'a';
  3783.       tableDir[12 + 16*j +  3] = 'p';
  3784.       tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
  3785.       tableDir[12 + 16*j +  5] = (char)0;
  3786.       tableDir[12 + 16*j +  6] = (char)0;
  3787.       tableDir[12 + 16*j +  7] = (char)0;
  3788.       tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
  3789.       tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
  3790.       tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
  3791.       tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
  3792.       tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
  3793.       tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
  3794.       tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >>  8) & 0xff);
  3795.       tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab)        & 0xff);
  3796.       pos += sizeof(cmapTab);
  3797.       ++j;
  3798.       dirCmap = gTrue;
  3799.     }
  3800.     if (!dirName && strncmp(tableHdrs[i].tag, "name", 4) > 0) {
  3801.       tableDir[12 + 16*j     ] = 'n';
  3802.       tableDir[12 + 16*j +  1] = 'a';
  3803.       tableDir[12 + 16*j +  2] = 'm';
  3804.       tableDir[12 + 16*j +  3] = 'e';
  3805.       tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
  3806.       tableDir[12 + 16*j +  5] = (char)0;
  3807.       tableDir[12 + 16*j +  6] = (char)0;
  3808.       tableDir[12 + 16*j +  7] = (char)0;
  3809.       tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
  3810.       tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
  3811.       tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
  3812.       tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
  3813.       tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
  3814.       tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
  3815.       tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >>  8) & 0xff);
  3816.       tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab)        & 0xff);
  3817.       pos += sizeof(nameTab);
  3818.       ++j;
  3819.       dirName = gTrue;
  3820.     }
  3821.     if (!dirName && strncmp(tableHdrs[i].tag, "post", 4) > 0) {
  3822.       tableDir[12 + 16*j     ] = 'p';
  3823.       tableDir[12 + 16*j +  1] = 'o';
  3824.       tableDir[12 + 16*j +  2] = 's';
  3825.       tableDir[12 + 16*j +  3] = 't';
  3826.       tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
  3827.       tableDir[12 + 16*j +  5] = (char)0;
  3828.       tableDir[12 + 16*j +  6] = (char)0;
  3829.       tableDir[12 + 16*j +  7] = (char)0;
  3830.       tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
  3831.       tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
  3832.       tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
  3833.       tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
  3834.       tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
  3835.       tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
  3836.       tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >>  8) & 0xff);
  3837.       tableDir[12 + 16*j + 15] = (char)( sizeof(postTab)        & 0xff);
  3838.       pos += sizeof(postTab);
  3839.       ++j;
  3840.       dirPost = gTrue;
  3841.     }
  3842.     tableDir[12 + 16*j     ] = tableHdrs[i].tag[0];
  3843.     tableDir[12 + 16*j +  1] = tableHdrs[i].tag[1];
  3844.     tableDir[12 + 16*j +  2] = tableHdrs[i].tag[2];
  3845.     tableDir[12 + 16*j +  3] = tableHdrs[i].tag[3];
  3846.     tableDir[12 + 16*j +  4] = (char)((tableHdrs[i].checksum >> 24) & 0xff);
  3847.     tableDir[12 + 16*j +  5] = (char)((tableHdrs[i].checksum >> 16) & 0xff);
  3848.     tableDir[12 + 16*j +  6] = (char)((tableHdrs[i].checksum >>  8) & 0xff);
  3849.     tableDir[12 + 16*j +  7] = (char)( tableHdrs[i].checksum        & 0xff);
  3850.     t = tableHdrs[i].offset + nNewTables * 16;
  3851.     tableDir[12 + 16*j +  8] = (char)((t >> 24) & 0xff);
  3852.     tableDir[12 + 16*j +  9] = (char)((t >> 16) & 0xff);
  3853.     tableDir[12 + 16*j + 10] = (char)((t >>  8) & 0xff);
  3854.     tableDir[12 + 16*j + 11] = (char)( t        & 0xff);
  3855.     tableDir[12 + 16*j + 12] = (char)((tableHdrs[i].length >> 24) & 0xff);
  3856.     tableDir[12 + 16*j + 13] = (char)((tableHdrs[i].length >> 16) & 0xff);
  3857.     tableDir[12 + 16*j + 14] = (char)((tableHdrs[i].length >>  8) & 0xff);
  3858.     tableDir[12 + 16*j + 15] = (char)( tableHdrs[i].length        & 0xff);
  3859.     ++j;
  3860.   }
  3861.   if (!dirCmap) {
  3862.     tableDir[12 + 16*j     ] = 'c';
  3863.     tableDir[12 + 16*j +  1] = 'm';
  3864.     tableDir[12 + 16*j +  2] = 'a';
  3865.     tableDir[12 + 16*j +  3] = 'p';
  3866.     tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
  3867.     tableDir[12 + 16*j +  5] = (char)0;
  3868.     tableDir[12 + 16*j +  6] = (char)0;
  3869.     tableDir[12 + 16*j +  7] = (char)0;
  3870.     tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
  3871.     tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
  3872.     tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
  3873.     tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
  3874.     tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
  3875.     tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
  3876.     tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >>  8) & 0xff);
  3877.     tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab)        & 0xff);
  3878.     pos += sizeof(cmapTab);
  3879.     ++j;
  3880.     dirCmap = gTrue;
  3881.   }
  3882.   if (!dirName) {
  3883.     tableDir[12 + 16*j     ] = 'n';
  3884.     tableDir[12 + 16*j +  1] = 'a';
  3885.     tableDir[12 + 16*j +  2] = 'm';
  3886.     tableDir[12 + 16*j +  3] = 'e';
  3887.     tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
  3888.     tableDir[12 + 16*j +  5] = (char)0;
  3889.     tableDir[12 + 16*j +  6] = (char)0;
  3890.     tableDir[12 + 16*j +  7] = (char)0;
  3891.     tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
  3892.     tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
  3893.     tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
  3894.     tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
  3895.     tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
  3896.     tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
  3897.     tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >>  8) & 0xff);
  3898.     tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab)        & 0xff);
  3899.     pos += sizeof(nameTab);
  3900.     ++j;
  3901.     dirName = gTrue;
  3902.   }
  3903.   if (!dirPost) {
  3904.     tableDir[12 + 16*j     ] = 'p';
  3905.     tableDir[12 + 16*j +  1] = 'o';
  3906.     tableDir[12 + 16*j +  2] = 's';
  3907.     tableDir[12 + 16*j +  3] = 't';
  3908.     tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
  3909.     tableDir[12 + 16*j +  5] = (char)0;
  3910.     tableDir[12 + 16*j +  6] = (char)0;
  3911.     tableDir[12 + 16*j +  7] = (char)0;
  3912.     tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
  3913.     tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
  3914.     tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
  3915.     tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
  3916.     tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
  3917.     tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
  3918.     tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >>  8) & 0xff);
  3919.     tableDir[12 + 16*j + 15] = (char)( sizeof(postTab)        & 0xff);
  3920.     pos += sizeof(postTab);
  3921.     ++j;
  3922.     dirPost = gTrue;
  3923.   }
  3924.  
  3925.   // write the table directory
  3926.   fwrite(tableDir, 1, 12 + 16 * nAllTables, out);
  3927.  
  3928.   // write the original tables
  3929.   fwrite(file + 12 + 16*nTables, 1, len - (12 + 16*nTables), out);
  3930.  
  3931.   // write the new tables
  3932.   for (i = 0; i < pad; ++i) {
  3933.     fputc((char)0, out);
  3934.   }
  3935.   if (!haveCmap) {
  3936.     fwrite(cmapTab, 1, sizeof(cmapTab), out);
  3937.   }
  3938.   if (!haveName) {
  3939.     fwrite(nameTab, 1, sizeof(nameTab), out);
  3940.   }
  3941.   if (!havePost) {
  3942.     fwrite(postTab, 1, sizeof(postTab), out);
  3943.   }
  3944.  
  3945.   gfree(tableDir);
  3946. }
  3947.